Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
KWH40
fml40-reference-implementation
Commits
f6e29bc2
Commit
f6e29bc2
authored
Oct 26, 2020
by
Jiahang Chen
Browse files
rewritten ml package
parent
dfa66f33
Pipeline
#348603
passed with stage
Changes
138
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
configs/config_my_dt_harvester.json
View file @
f6e29bc2
{
"thingId"
:
"s3i:b6d1cc6d-896c-40fe-9403-b5b7682b1d03"
,
"policyId"
:
"s3i:b6d1cc6d-896c-40fe-9403-b5b7682b1d03"
,
"attributes"
:
{
"class"
:
"ml40::Thing"
,
"name"
:
"my_dt_harvester"
,
"roles"
:
[{
"class"
:
"fml40::Harvester"
}],
"features"
:
[{
"class"
:
"fml40::ProvidesProductionData"
},
{
"class"
:
"fml40::AcceptsFellingJobs"
},
{
"class"
:
"ml40::Composite"
,
"targets"
:
[{
"class"
:
"ml40::Thing"
,
"name"
:
"my_engine"
,
"roles"
:
[{
"class"
:
"ml40::Engine"
}],
"features"
:
[{
"class"
:
"ml40::RotationalSpeed"
,
"rpm"
:
5
}]},
{
"class"
:
"ml40::Thing"
,
"name"
:
"my_bord_computer"
,
"roles"
:
[{
"class"
:
"ml40::MachineUI"
}],
"features"
:
[]}]}]}}
\ No newline at end of file
{
"thingId"
:
"s3i:b6d1cc6d-896c-40fe-9403-b5b7682b1d03"
,
"policyId"
:
"s3i:b6d1cc6d-896c-40fe-9403-b5b7682b1d03"
,
"attributes"
:
{
"class"
:
"ml40::Thing"
,
"name"
:
"my_dt_harvester"
,
"roles"
:
[{
"class"
:
"fml40::Harvester"
}],
"features"
:
[{
"class"
:
"fml40::ProvidesProductionData"
},
{
"class"
:
"fml40::AcceptsFellingJobs"
},
{
"class"
:
"ml40::Composite"
,
"targets"
:
[{
"class"
:
"ml40::Thing"
,
"name"
:
"my_engine"
,
"roles"
:
[{
"class"
:
"ml40::Engine"
}],
"features"
:
[{
"class"
:
"ml40::RotationalSpeed"
,
"rpm"
:
2001
}]},
{
"class"
:
"ml40::Thing"
,
"name"
:
"my_bord_computer"
,
"roles"
:
[{
"class"
:
"ml40::MachineUI"
}],
"features"
:
[]}]}]}}
\ No newline at end of file
dt_creation.py
View file @
f6e29bc2
import
s3i
import
json
import
jwt
import
requests
from
ml.tools
import
load_config
,
make_thing_config
,
make_sub_thing
from
ml.dt_factory
import
create_dt_ref
from
ml.dt_factory
import
create_dt_ref
,
build_feature
,
add_function_impl_obj
from
ml.fml40.features.functionalities.accepts_felling_jobs
import
AcceptsFellingJobs
from
ml.ml40.features.properties.values.documents.jobs.job_status
import
JobStatus
from
ml.app_logger
import
APP_LOGGER
,
setup_logger
import
time
dt_creation_app_id
=
"s3i:a44bd6dc-c607-4574-9b16-cf8579819356"
dt_creation_app_secret
=
"970ebe57-7dfb-4090-8c38-4b44111d5288"
...
...
@@ -34,6 +34,7 @@
dt_id = resp.json().get("identifier", None)
dt_secret = resp.json().get("secret", None)
s3i_config.create_broker_queue(thing_id=dt_id)
res = s3i_config.create_cloud_copy(thing_id=dt_id)
print(dt_id)
"""
...
...
@@ -43,40 +44,90 @@
config_engine
=
make_sub_thing
(
name
=
"my_engine"
,
roles
=
[{
"class"
:
"ml40::Engine"
}],
features
=
[
{
"class"
:
"ml40::RotationalSpeed"
,
"rpm"
:
5
}
"rpm"
:
2001
}
])
config_cran
=
make_sub_thing
(
name
=
"my_bord_computer"
,
roles
=
[{
"class"
:
"ml40::MachineUI"
}])
config_file_name
=
make_thing_config
(
dt_id
=
dt_id
,
name
=
dt_name
,
roles
=
[{
"class"
:
"fml40::Harvester"
}],
features
=
[{
"class"
:
"fml40::ProvidesProductionData"
},
{
"class"
:
"fml40::AcceptsFellingJobs"
},
{
"class"
:
"ml40::Composite"
,
"targets"
:
[
config_engine
,
config_cran
]}])
features
=
[{
"class"
:
"fml40::ProvidesProductionData"
},
{
"class"
:
"fml40::AcceptsFellingJobs"
},
{
"class"
:
"ml40::Composite"
,
"targets"
:
[
config_engine
,
config_cran
]}])
setup_logger
(
dt_name
)
dt_model
=
load_config
(
'configs/{}'
.
format
(
config_file_name
))
dt
=
create_dt_ref
(
model
=
dt_model
,
grant_type
=
"password"
,
secret
=
dt_secret
,
username
=
username
,
password
=
password
,
is_broker_rest
=
True
,
is_broker
=
True
,
is_repo
=
True
)
dt_ref
=
create_dt_ref
(
model
=
dt_model
,
grant_type
=
"password"
,
secret
=
dt_secret
,
username
=
username
,
password
=
password
,
is_broker_rest
=
True
,
is_broker
=
True
,
is_repo
=
False
)
dt_proxy
=
dt_ref
.
proxy
()
dt_proxy
.
run_forever
()
dt
.
run_forever
()
class
AcceptsFellingJobsImpl
(
AcceptsFellingJobs
):
def
my_accept_job_func
(
self
,
job
):
APP_LOGGER
.
info
(
"Checking job with my impl function."
)
return
self
.
add_to_job_list
(
job
)
dt_proxy
.
add_function_impl
(
AcceptsFellingJobsImpl
,
"fml40::AcceptsFellingJobs"
)
#print(dt_proxy.features.get())
print
(
dt_proxy
.
features
.
get
()[
"ml40::Composite"
].
proxy
().
to_json
().
get
())
#print(dt_proxy.features.get()["Composite"].proxy().targets.get()[0].proxy().features.get())
#print(dt_proxy.features.get()["Composite"].proxy().targets.get()[0].proxy().features.get()["RotationalSpeed"].proxy().rpm.get())
#print(dt_proxy.roles.get())
#print(dt_proxy.name.get())
#print(dt_proxy.proxy_functionalities.get())
def
__init__
(
self
,
name
=
""
,
identifier
=
""
):
super
(
AcceptsFellingJobs
,
self
).
__init__
(
name
=
name
,
identifier
=
identifier
)
self
.
job_list
=
[]
def
acceptJob
(
self
,
job
):
APP_LOGGER
.
info
(
"Checking if the felling job can be accepted."
)
if
isinstance
(
job
,
dict
):
try
:
felling_job
=
build_feature
(
feature
=
job
)
for
job
in
self
.
job_list
:
if
job
.
identifier
==
felling_job
.
identifier
:
APP_LOGGER
.
info
(
"Job with ID {} has been rejected, because this job was already accepted"
.
format
(
felling_job
.
identifier
))
return
False
felling_job
.
status
=
JobStatus
.
InProgress
.
name
self
.
job_list
.
append
(
felling_job
)
APP_LOGGER
.
info
(
"Job with ID {} has been accepted"
.
format
(
felling_job
.
identifier
))
return
True
except
:
APP_LOGGER
.
info
(
"Job with ID {} has been rejected"
.
format
(
felling_job
.
identifier
))
return
False
def
queryJobStatus
(
self
,
identifier
):
APP_LOGGER
.
info
(
"Checking the job status of job {}"
.
format
(
identifier
))
for
job
in
self
.
job_list
:
if
job
.
identifier
==
identifier
:
APP_LOGGER
.
info
(
"Job {} is now in status {}"
.
format
(
identifier
,
job
.
status
))
return
{
"identifier"
:
identifier
,
"status"
:
job
.
status
}
APP_LOGGER
.
info
(
"Job {} can not be queried"
.
format
(
identifier
))
return
{
"identifier"
:
identifier
,
"status"
:
"NOT FOUND"
}
def
removeJob
(
self
,
identifier
):
APP_LOGGER
.
info
(
"Checking if i can remove the job {}"
.
format
(
identifier
))
for
job
in
self
.
job_list
:
if
job
.
identifier
==
identifier
:
self
.
job_list
.
remove
(
job
)
APP_LOGGER
.
info
(
"Job {} removed"
.
format
(
identifier
))
return
True
APP_LOGGER
.
info
(
"Job {} can not be found"
.
format
(
identifier
))
return
False
def
simulate_rpm
():
my_engine
=
dt
.
features
[
"ml40::Composite"
].
targets
[
"my_engine"
]
tank
=
"up"
while
True
:
if
tank
==
"down"
:
__new_rpm
=
my_engine
.
features
[
"ml40::RotationalSpeed"
].
rpm
-
10
if
__new_rpm
<
2000
:
tank
=
"up"
elif
tank
==
"up"
:
__new_rpm
=
my_engine
.
features
[
"ml40::RotationalSpeed"
].
rpm
+
10
if
__new_rpm
>
2500
:
tank
=
"down"
my_engine
.
features
[
"ml40::RotationalSpeed"
].
rpm
=
__new_rpm
time
.
sleep
(
1
)
add_function_impl_obj
(
dt
,
AcceptsFellingJobsImpl
,
"fml40::AcceptsFellingJobs"
)
dt
.
add_user_def
(
func
=
simulate_rpm
)
dt_creation_hmi.py
View file @
f6e29bc2
...
...
@@ -2,13 +2,10 @@
import
jwt
import
uuid
from
ml.tools
import
find_broker_endpoint
,
make_thing_config
,
load_config
,
make_feature_config
from
ml.identifier
import
ID
from
ml.dt_factory
import
create_dt_ref
,
create_feature_ref
from
ml.fml40.features.properties.values.documents.jobs.felling_job
import
FellingJob
from
ml.identifier
import
ID
from
ml.dt_factory
import
create_dt_ref
,
build_feature
from
ml.app_logger
import
setup_logger
import
requests
import
json
,
time
import
json
username
=
"chen"
password
=
"8810515"
...
...
@@ -17,63 +14,69 @@
setup_logger
(
"my HMI"
)
config_file_name
=
make_thing_config
(
dt_id
=
hmi_id
,
name
=
"my HMI"
,
roles
=
[{
"class"
:
"ml40::HMI"
}],
)
)
hmi_model
=
load_config
(
'configs/{}'
.
format
(
config_file_name
))
hmi_ref
=
create_dt_ref
(
model
=
hmi_model
,
grant_type
=
"password"
,
secret
=
hmi_secret
,
username
=
username
,
password
=
password
,
is_broker_rest
=
True
,
is_broker
=
True
,
is_repo
=
False
)
hmi_proxy
=
hmi_ref
.
proxy
()
hmi_proxy
.
run_forever
()
hmi
=
create_dt_ref
(
model
=
hmi_model
,
grant_type
=
"password"
,
secret
=
hmi_secret
,
username
=
username
,
password
=
password
,
is_broker_rest
=
True
,
is_broker
=
True
,
is_repo
=
False
)
hmi
.
run_forever
()
hmi_endpoint
=
find_broker_endpoint
(
hmi
.
dir
,
hmi_id
)
receiver
=
input
(
"[S³I]: Please enter the id of your digital twin: "
)
"""
Print out thing entry from directory and repository
"""
print
(
hmi
.
dir
.
queryThingIDBased
(
thingID
=
receiver
))
print
(
hmi
.
repo
.
queryThingIDBased
(
thingID
=
receiver
))
hmi_endpoint
=
find_broker_endpoint
(
hmi_proxy
.
dir
.
get
(),
hmi_id
)
serv_req
=
s3i
.
messages
.
ServiceRequest
()
subFeatures
=
[{
"class"
:
"fml40::Assortment"
,
"grade"
:
"fl"
,
"name"
:
"Stammholz Abschnitte"
,
"subFeatures"
:
[
{
"class"
:
"fml40::ThicknessClass"
,
"name"
:
">"
},
{
"class"
:
"fml40::WoodQuality"
,
"name"
:
"B-C"
},
{
"class"
:
"fml40::HarvestingParameters"
,
"cuttingLengths"
:
20
},
{
"class"
:
"fml40::TreeType"
,
"name"
:
"Spruce"
,
"conifer"
:
True
},
{
"class"
:
"fml40::HarvestedVolume"
,
"volume"
:
140
}
]
}]
id
=
ID
(
identifier
=
"s3i:721b1947-2807-4bc3-a6d3-fe9e97de90d0"
).
ID
feature_config_json
=
make_feature_config
(
class_name
=
"fml40::FellingJob"
,
identifier
=
id
,
subFeatures
=
subFeatures
)
felling_job_ref
=
create_feature_ref
(
model
=
feature_config_json
,
thing_ref
=
hmi_ref
)
felling_job_proxy
=
felling_job_ref
.
proxy
()
print
(
felling_job_proxy
.
to_json
().
get
())
receiver
=
input
(
"[S³I]: Please enter the id of your digital twin: "
)
"class"
:
"fml40::Assortment"
,
"grade"
:
"fl"
,
"name"
:
"Stammholz Abschnitte"
,
"subFeatures"
:
[
{
"class"
:
"fml40::ThicknessClass"
,
"name"
:
">"
},
{
"class"
:
"fml40::WoodQuality"
,
"name"
:
"B-C"
},
{
"class"
:
"fml40::HarvestingParameters"
,
"cuttingLengths"
:
20
},
{
"class"
:
"fml40::TreeType"
,
"name"
:
"Spruce"
,
"conifer"
:
True
},
{
"class"
:
"fml40::HarvestedVolume"
,
"volume"
:
140
}
]
}]
feature_config_json
=
make_feature_config
(
class_name
=
"fml40::FellingJob"
,
subFeatures
=
subFeatures
,
name
=
"my_felling_job"
)
felling_job
=
build_feature
(
feature
=
feature_config_json
)
serv_req
.
fillServiceRequest
(
senderUUID
=
hmi_id
,
receiverUUID
=
[
receiver
],
sender_endpoint
=
hmi_endpoint
,
serviceType
=
"fml40::AcceptsFellingJobs/removeJob"
,
parameters
=
{
"identifier"
:
id
},
#parameters={"job": felling_job_proxy.to_json().get()},
msgUUID
=
str
(
uuid
.
uuid4
())
#serviceType="fml40::AcceptsFellingJobs/acceptJob",
parameters
=
{
"identifier"
:
"s3i:d09214a7-46bb-4672-b4e0-2c0aa0e395a3"
},
#parameters={"job": felling_job.to_json()},
msgUUID
=
"s3i:{}"
.
format
(
uuid
.
uuid4
())
)
receiver_endpoint
=
find_broker_endpoint
(
hmi_proxy
.
dir
.
get
(),
thing_id
=
receiver
)
resp
=
hmi_proxy
.
broker
.
get
().
send
([
receiver_endpoint
],
json
.
dumps
(
serv_req
.
msg
))
getv_req
=
s3i
.
GetValueRequest
()
rpm_path
=
"attributes/features/ml40::Composite/targets/ml40::Engine/features/ml40::RotationalSpeed/rpm"
getv_req
.
fillGetValueRequest
(
senderUUID
=
hmi_id
,
receiverUUID
=
[
receiver
],
sender_endpoint
=
hmi_endpoint
,
attributePath
=
rpm_path
,
msgUUID
=
"s3i:{}"
.
format
(
uuid
.
uuid4
())
)
receiver_endpoint
=
find_broker_endpoint
(
hmi
.
dir
,
thing_id
=
receiver
)
resp
=
hmi
.
broker
.
send
([
receiver_endpoint
],
json
.
dumps
(
serv_req
.
msg
))
ml/dt_factory.py
View file @
f6e29bc2
""" Implements a factory for managing digital twins."""
import
sys
,
json
from
ml.managing_actor
import
ManagingActor
from
ml.app_logger
import
APP_LOGGER
from
ml.tools
import
remove_namespace
"""
from ml.thing import Thing
from ml.ml40.features.properties.associations.composite import Composite
from ml.fml40.roles.dts.machines.harvester import Harvester
from ml.fml40.features.functionalities.accepts_felling_jobs import AcceptsFellingJobs
from ml.ml40.features.properties.values.rotational_speed import RotationalSpeed
from ml.ml40.roles.dts.parts.engine import Engine
from ml.fml40.features.functionalities.provides_production_data import ProvidesProductionData
from ml.ml40.roles.hmis.machine_ui import MachineUI
from ml.fml40.features.properties.values.documents.jobs.felling_job import FellingJob
from ml.ml40.roles.hmis.hmi import HMI
from ml.fml40.features.properties.values.assortment import Assortment
from ml.fml40.features.properties.values.thickness_class import ThicknessClass
from ml.fml40.features.properties.values.wood_quality import WoodQuality
from ml.fml40.features.properties.values.harvesting_parameter import HarvestingParameters
from ml.fml40.features.properties.values.tree_type import TreeType
from ml.fml40.features.properties.values.harvested_volume import HarvestedVolume
"""
from
ml.thing
import
Thing
from
ml.ml40.roles.servives.service
import
Service
from
ml.ml40.roles.hmis.app
import
App
from
ml.ml40.roles.hmis.dashboard
import
Dashboard
...
...
@@ -54,10 +68,10 @@
from
ml.fml40.roles.dts.sites.mill.papermill
import
Papermill
from
ml.fml40.roles.dts.sites.mill.sawmill
import
Sawmill
from
ml.ml40.features.properties.association
import
Association
from
ml.ml40.features.properties.composite
import
Composite
from
ml.ml40.features.properties.association
s.association
import
Association
from
ml.ml40.features.properties.
associations.
composite
import
Composite
from
ml.ml40.features.properties.property
import
Property
from
ml.ml40.features.properties.shared
import
Shared
from
ml.ml40.features.properties.
associations.
shared
import
Shared
from
ml.ml40.features.properties.values.address
import
Address
from
ml.ml40.features.properties.values.dimensions
import
Dimensions
from
ml.ml40.features.properties.values.generic_property
import
GenericProperty
...
...
@@ -155,32 +169,6 @@
# TODO: Get rid of this global variable
# TODO: automatically get all classes in modul
DT_FACTORY
=
{}
"""
DT_FACTORY["Thing"] = Thing
DT_FACTORY["Composite"] = Composite
DT_FACTORY["Service"] = Service
DT_FACTORY["HMI"] = HMI
DT_FACTORY["Harvester"] = Harvester
DT_FACTORY["LogTruck"] = LogTruck
DT_FACTORY["ManagesJobs"] = ManagesJobs
DT_FACTORY["Location"] = Location
DT_FACTORY["Shared"] = Shared
DT_FACTORY["Weight"] = Weight
DT_FACTORY["Moisture"] = Moisture
DT_FACTORY["AcceptsProximityAlert"] = AcceptsProximityAlert
DT_FACTORY["AcceptsFellingJobs"] = AcceptsFellingJobs
DT_FACTORY["ProvidesProductionData"] = ProvidesProductionData
DT_FACTORY["Harvests"] = Harvests
DT_FACTORY["Forwards"] = Forwards
DT_FACTORY["AcceptsForwardingJobs"] = AcceptsForwardingJobs
DT_FACTORY["ProvidesPassabilityInformation"] = ProvidesPassabilityInformation
DT_FACTORY["ProvidesMoisturePrediction"] = ProvidesMoisturePrediction
DT_FACTORY["MoisturePredictionReport"] = MoisturePredictionReport
DT_FACTORY["AcceptsPassabilityReport"] = AcceptsPassabilityReport
"""
import
sys
,
inspect
...
...
@@ -188,166 +176,100 @@
for
member
in
clsmembers
:
DT_FACTORY
[
member
[
0
]]
=
member
[
1
]
def
get_dt_names
():
"""Returns a list containg the names of all registered digital twins.
"""
dt_names
=
list
(
map
(
lambda
x
:
x
,
DT_FACTORY
.
keys
()))
return
dt_names
def
create_dt_with_idp
(
config
,
id_p
):
"""Creates and returns a ditigal twin.
:param config: A json-object describing the digital twin.
:param i_d_p: A s3i.IdentityProvider object
:returns: Tuple (digital twin, access token)
:rtype: tuple(config[type], str)
"""
dt_type
=
config
[
"type"
]
d_t
=
DT_FACTORY
.
get
(
dt_type
,
ManagingActor
)
return
d_t
# def create_dt(config):
# """Creates and returns a ditigal twin and returns .
# :param config: A json-object describing the digital twin.
# :returns: Tuple (digital twin, access token)
# :rtype: tuple(config[type], str)
# """
# id_p = get_idp(config)
# dt_type = config["type"]
# d_t = DT_FACTORY.get(dt_type, ManagingActor)(id_p, config)
# return d_t
def
build_sub_features
(
feature_ins
,
feature
):
sub_features
=
feature
.
get
(
"subFeatures"
,
[])
###
def
build_sub_featrues
(
thing_ref
,
feature_proxy
,
json_feature
):
json_sub_features
=
json_feature
.
get
(
"subFeatures"
,
[])
temp_dict
=
{}
for
json_sub_feature
in
json_sub_features
:
#str_sub_feature = json.dumps(json_sub_feature).replace("fml40::", "").replace("ml40::", "").replace("'", '"')
#json_sub_feature = json.loads(str_sub_feature)
sub_feature_name
=
json_sub_feature
.
get
(
"class"
,
""
)
sub_feature
=
DT_FACTORY
.
get
(
remove_namespace
(
sub_feature_name
),
None
)
if
sub_feature
is
None
:
APP_LOGGER
.
critical
(
"Subfeature: %s is missing"
%
sub_feature_name
)
for
sub_f
in
sub_features
:
sub_f_name
=
sub_f
.
get
(
"class"
,
""
)
sub_f_obj
=
DT_FACTORY
.
get
(
remove_namespace
(
sub_f_name
),
None
)
if
sub_f_obj
is
None
:
APP_LOGGER
.
critical
(
"Subfeature: %s is missing"
%
sub_f_name
)
else
:
APP_LOGGER
.
debug
(
"Adding subfeature: %s"
%
sub_feature_name
)
sub_feature_ref
=
sub_feature
.
start
(
sub_feature_name
,
thing_ref
)
temp_dict
[
sub_feature_name
]
=
sub_feature_ref
for
key
in
json_sub_feature
.
keys
():
APP_LOGGER
.
debug
(
"Adding subfeature: %s"
%
sub_f_name
)
sub_f_instance
=
sub_f_obj
()
for
key
in
sub_f
.
keys
():
if
key
==
"targets"
:
build_sub_thing
(
feature_proxy
,
sub_f
eature
)
build_sub_thing
(
sub_f_instance
,
sub_f
)
elif
key
==
"subFeatures"
:
build_sub_featrues
(
thing_ref
,
sub_feature_ref
.
proxy
(),
json_sub_feature
)
build_sub_features
(
sub_f_instance
,
sub_f
)
else
:
setattr
(
sub_feature_ref
.
proxy
(),
key
,
json_sub_feature
[
key
])
feature_proxy
.
subFeatures
=
temp_dict
setattr
(
sub_f_instance
,
key
,
sub_f
[
key
])
feature_ins
.
subFeatures
[
sub_f_name
]
=
sub_f_instance
def
build_sub_thing
(
feature_
proxy
,
json_feature
):
def
build_sub_thing
(
feature_
ins
,
json_feature
):
json_sub_things
=
json_feature
.
get
(
"targets"
,
[])
for
json_sub_thing
in
json_sub_things
:
sub_thing_ref
=
create_dt_ref
(
model
=
{
"attributes"
:
json_sub_thing
})
feature_proxy
.
targets
.
get
().
append
(
sub_thing_ref
)
sub_thing_name
=
json_sub_thing
.
get
(
"name"
,
None
)
feature_ins
.
targets
[
sub_thing_name
]
=
sub_thing_ref
def
build
(
thing
_ref
,
attributes
):
def
build
(
thing
,
attributes
):
if
not
isinstance
(
attributes
,
dict
):
APP_LOGGER
.
critical
(
"Attributes is no valid json"
)
return
thing_proxy
=
thing_ref
.
proxy
()
roles
=
attributes
.
get
(
"roles"
,
[])
__build_roles
(
thing_ref
,
thing_proxy
,
roles
)
json_features
=
attributes
.
get
(
"features"
,
[])
for
json_feature
in
json_features
:
feature_name
=
json_feature
.
get
(
"class"
,
""
)
feature_pars
=
json_feature
feature
=
DT_FACTORY
.
get
(
remove_namespace
(
feature_name
),
None
)
if
feature
is
None
:
APP_LOGGER
.
critical
(
"Feature: %s is missing"
%
feature_name
)
else
:
APP_LOGGER
.
debug
(
"Adding feature: %s"
%
feature_name
)
feature_ref
=
feature
.
start
(
feature_name
,
thing_ref
)
feature_proxy
=
feature_ref
.
proxy
()
for
key
in
feature_pars
.
keys
():
if
key
==
"targets"
:
build_sub_thing
(
feature_proxy
,
json_feature
)
elif
key
==
"subFeatures"
:
build_sub_featrues
(
thing_ref
,
feature_proxy
,
json_feature
)
else
:
setattr
(
feature_proxy
,
key
,
feature_pars
[
key
])
thing_proxy
.
features
.
get
()[
feature_proxy
.
name
.
get
()]
=
feature_ref
def
__build_roles
(
thing_ref
,
thing_proxy
,
roles
):
for
role
in
roles
:
role_name
=
role
.
get
(
"class"
,
""
)
role
=
DT_FACTORY
.
get
(
remove_namespace
(
role_name
),
None
)
if
role
is
None
:
APP_LOGGER
.
critical
(
"Roles: %s is missing"
%
role_name
)
else
:
APP_LOGGER
.
debug
(
"Adding roles: %s"
%
role_name
)
role_ref
=
role
.
start
(
role_name
,
thing_ref
)
thing_proxy
.
roles
.
get
()[
role_name
]
=
role_ref
def
create_feature_ref
(
model
,
thing_ref
):
if
not
isinstance
(
model
,
dict
):
APP_LOGGER
.
error
(
"The input feature model is no valid json"
)
feature_class
=
model
.
get
(
"class"
,
None
)
if
feature_class
is
None
:
APP_LOGGER
.
error
(
"Incomplete model: class missing"
)
feature
=
DT_FACTORY
.
get
(
feature_class
.
replace
(
"fml40::"
,
""
).
replace
(
"ml40::"
,
""
),
""
)
feature_ref
=
feature
.
start
(
feature_class
,
thing_ref
)
feature_proxy
=
feature_ref
.
proxy
()
feature_id
=
model
.
get
(
"identifier"
,
None
)
print
(
feature_id
)
if
feature_id
is
not
None
:
feature_proxy
.
identifier
=
feature_id
feature_sub_features
=
model
.
get
(
"subFeatures"
,
None
)
if
feature_sub_features
is
not
None
:
build_sub_featrues
(
thing_ref
,
feature_proxy
,
{
"subFeatures"
:
feature_sub_features
})
role_instance
=
build_role
(
role
)
thing
.
roles
[
role
.
get
(
"class"
)]
=
role_instance
return
feature_ref
json_features
=
attributes
.
get
(
"features"
,
[])
for
feature
in
json_features
:
feature_ins
=
build_feature
(
feature
=
feature
)
thing
.
features
[
feature
.
get
(
"class"
)]
=
feature_ins
def
build_role
(
role
):
role_class_name
=
role
.
get
(
"class"
,
""
)
role_obj
=
DT_FACTORY
.
get
(
remove_namespace
(
role_class_name
),
None
)
if
role_obj
is
None
:
APP_LOGGER
.
critical
(
"Roles: %s is missing"
%
role_class_name
)
else
:
APP_LOGGER
.
debug
(
"Adding roles: %s"
%
role_class_name
)
role_instance
=
role_obj
()
return
role_instance
def
build_feature
(
feature
):
feature_class_name
=
feature
.
get
(
"class"
,
""
)
feature_obj
=
DT_FACTORY
.
get
(
remove_namespace
(
feature_class_name
),
None
)
if
feature_obj
is
None
:
APP_LOGGER
.
critical
(
"Feature: %s is missing"
%
feature_class_name
)
else
:
APP_LOGGER
.
debug
(
"Adding feature: %s"
%
feature_class_name
)
feature_instance
=
feature_obj
()
for
key
in
feature
.
keys
():
if
key
==
"targets"
:
build_sub_thing
(
feature_instance
,
feature
)
elif
key
==
"subFeatures"
:
build_sub_features
(
feature_instance
,
feature
)
else
:
setattr
(
feature_instance
,
key
,
feature
[
key
])
return
feature_instance
def
add_function_impl_obj
(
thing
,
impl_obj
,
feature_name
):
feature
=
thing
.
features
.
get
(
feature_name
,
None
)
if
feature
is
None
:
APP_LOGGER
.
critical
(
"Functionality %s is not one of the build-in functionalities"
%
feature_name
)
else
:
APP_LOGGER
.
debug
(
"Implementation object is added into the functionality %s"
%
feature_name
)
thing
.
features
[
feature_name
]
=
impl_obj
(
feature_name
)
def
create_dt_ref
(
model
,
grant_type
=
"password"
,
secret
=
""
,
username
=
None
,
password
=
None
,
is_broker_rest
=
False
,
is_broker
=
False
,
is_repo
=
False
):
"""Creates a ditigal twin, runs it in an own thread and returns a
reference to it.
:param config: A json-object describing the digital twin.
:param i_d_p: A s3i.IdentityProvider object
:returns: Tuple (digital twin, access token)
:rtype: tuple(Reference, str)
"""
attributes
=
model
.
get
(
"attributes"
,
None
)
if
attributes
is
None
:
sys
.
exit
(
"Incomplete model: attributes missing!"
)
#attributes = json.dumps(attributes).replace("fml40::", "").replace("ml40::", "").replace("'", '"')
#attributes = json.loads(attributes)
thing_type
=
remove_namespace
(
attributes
.
get
(
"class"
,
""
))
if
thing_type
==
""
:
print
(
"Unknown type %s"
%
thing_type
)
sys
.
exit
()
roles
=
attributes
.
get
(
"roles"
,
None
)
if
roles
is
None
:
...
...
@@ -355,8 +277,10 @@ def create_dt_ref(model, grant_type="password",
thing_name
=
attributes
.
get
(
"name"
,
""
)
APP_LOGGER
.
debug
(
"Creating ditigtal twin {} with id {}"
.
format
(
thing_name
,
model
.
get
(
"thingId"
,
""
)))
d_t
=
DT_FACTORY
.
get
(
thing_type
,
ManagingActor
)
thing_ref
=
d_t
.
start
(
d_t
=
DT_FACTORY
.
get
(
thing_type
)
thing_ref
=
d_t
(
model
=
model
,
grant_type
=
grant_type
,
client_secret
=
secret
,
...
...
ml/feature.py
0 → 100644
View file @
f6e29bc2
from
ml.identifier
import
ID
import
sys
from
abc
import
ABC
class
Feature
(
ABC
):