Commit f906a51d authored by Jiahang Chen's avatar Jiahang Chen
Browse files

ADD Notebooks for workshop

parent b286ffd2
Pipeline #338072 passed with stage
in 14 seconds
......@@ -18,4 +18,208 @@ logs
credentials/*.json
credentials/*.txt
!./credentials/collection.txt.gpg
\ No newline at end of file
!./credentials/collection.txt.gpg
# Created by https://www.gitignore.io/api/python,pycharm+all
# Edit at https://www.gitignore.io/?templates=python,pycharm+all
### PyCharm+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### PyCharm+all Patch ###
# Ignores the whole .idea folder and all .iml files
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
.idea/
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
modules.xml
.idea/misc.xml
*.ipr
# Sonarlint plugin
.idea/sonarlint
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# End of https://www.gitignore.io/api/python,pycharm+all
# don't commit actual config file
config.py
# venv
venv/*
\ No newline at end of file
{
"thingId": "s3i:bea74f50-fa6c-4aba-b7f8-90153b401ffc",
"policyId": "s3i:bea74f50-fa6c-4aba-b7f8-90153b401ffc",
"attributes": {
"class": "ml40::Thing",
"name": "created DT Harvester for workshop",
"roles": [
{
"class": "fml40::Harvester"
}
],
"features": [
{
"class": "fml40::ProvidesProductionData"
},
{
"class": "fml40::AcceptsFellingJobs"
},
{
"class": "ml40::ManagesJobs"
}
]
}
}
\ No newline at end of file
import s3i
import json
import jwt
from ml.tools import load_config, get_s3i_broker, get_receiver_callback_func
from ml.dt_factory import create_dt_ref
from ml.fml40.features.functionalities.accepts_felling_jobs import AcceptsFellingJobs
dt_creation_app_id = "s3i:a44bd6dc-c607-4574-9b16-cf8579819356"
dt_creation_app_secret = "970ebe57-7dfb-4090-8c38-4b44111d5288"
print("KWH application to create a dt, please log in!")
#username = input('[S3I]: Please enter your username:').strip('," ')
#password = input('[S3I]: Please enter your password:')
username = "KWH-Team"
password = "V4yuJ31izh0GCH36954O"
print("Your credentials are sent to S3I IdentityProvider.")
s3i_identity_provider = s3i.IdentityProvider(grant_type='password',
identity_provider_url="https://idp.s3i.vswf.dev/",
realm='KWH',
client_id=dt_creation_app_id,
client_secret=dt_creation_app_secret,
username=username,
password=password)
access_token = s3i_identity_provider.get_token(s3i.TokenType.ACCESS_TOKEN)
''' decode the access token'''
parsed_username = jwt.decode(access_token, verify=False)["preferred_username"]
print("Token received, " + parsed_username + " logged in.")
### create identity of digital twin
dt_secret = "c49e4050-d194-4f08-90c5-e17fd5befba5"
dt_model = load_config('configs/config_dt.json')
dt_ref = create_dt_ref(model=dt_model, grant_type="password", secret=dt_secret, username=username, password=password,
is_broker=True, is_repo=False)
dt_proxy = dt_ref.proxy()
dt_proxy.run_forever()
class AcceptsFellingJobsImpl(AcceptsFellingJobs):
def acceptJob(self, job):
print("i have accepted a job {}".format(job))
return True
dt_proxy.add_function_impl(AcceptsFellingJobsImpl, "AcceptsFellingJobs")
import s3i
import jwt
import uuid
username = "chen"
password = "8810515"
client_id = "s3i:b4f72a11-fb3d-47a3-b499-e7a88eaa5fe1"
client_secret = "84df6340-9d64-4ae6-9076-86c224ec484a"
s3i_identity_provider = s3i.IdentityProvider(grant_type='password',
identity_provider_url="https://idp.s3i.vswf.dev/",
realm='KWH',
client_id=client_id,
client_secret=client_secret,
username=username,
password=password)
access_token = s3i_identity_provider.get_token(s3i.TokenType.ACCESS_TOKEN)
''' decode the access token'''
parsed_username = jwt.decode(access_token, verify=False)["preferred_username"]
print("Token received, " + parsed_username + " logged in.")
s3i_dir = s3i.Directory(s3i_dir_url="https://dir.s3i.vswf.dev/api/2/", token=access_token)
hmi_json = s3i_dir.queryThingIDBased(thingID=client_id)
hmi_endpoints = hmi_json["attributes"].get("allEndpoints", None)
hmi_s3ib_ep = ""
for hmi_ep in hmi_endpoints:
if "s3ib" in hmi_ep:
hmi_s3ib_ep = hmi_ep
serv_req = s3i.messages.ServiceRequest()
serv_req.fillServiceRequest(
senderUUID=client_id, receiverUUID=["s3i:bea74f50-fa6c-4aba-b7f8-90153b401ffc"], sender_endpoint=hmi_s3ib_ep,
serviceType="AcceptsFellingJob/acceptJob",
parameters={"job": "fml40::FellingJob"},
msgUUID=str(uuid.uuid4())
)
my_dt_json = s3i_dir.queryThingIDBased(thingID="s3i:bea74f50-fa6c-4aba-b7f8-90153b401ffc")
dt_endpoints = my_dt_json["attributes"].get("allEndpoints", None)
dt_ep = ""
for temp in dt_endpoints:
if "s3ib" in temp:
dt_ep = temp
s3i_broker = s3i.Broker(auth_form="Username/Password", username=" ", password=access_token,
host="rabbitmq.s3i.vswf.dev")
s3i_broker.send([dt_ep], serv_req.msg.__str__())
""" Implements a factory for managing digital twins."""
import sys
import sys, json
from s3i import IdentityProvider
from s3i import TokenType
from ml.tools import get_idp
......@@ -13,7 +13,7 @@
from customer_code_example.forwarder_komatsu import komatsu
from customer_code_example.mini_tractor_driver import MiniTractorDriver
from ml.ml40.roles.service.service import Service
from ml.ml40.roles.servives.service import Service
from ml.ml40.features.functionalities.manages_jobs import ManagesJobs
from ml.ml40.features.properties.values.location import Location
from ml.ml40.features.properties.shared import Shared
......@@ -47,28 +47,29 @@
)
# TODO: Get rid of this global variable
# TODO: automatically get all classes in modul
DT_FACTORY = {}
DT_FACTORY["Service"] = Service
DT_FACTORY["ml40::Thing"] = Thing
DT_FACTORY["ml40::ManagesJobs"] = ManagesJobs
DT_FACTORY["ml40::Location"] = Location
DT_FACTORY["ml40::Composite"] = Composite
DT_FACTORY["ml40::Shared"] = Shared
DT_FACTORY["ml40::Weight"] = Weight
DT_FACTORY["ml40::Moisture"] = Moisture
DT_FACTORY["fml40::AcceptsProximityAlert"] = AcceptsProximityAlert
DT_FACTORY["fml40::AcceptsFellingJobs"] = AcceptsFellingJobs
DT_FACTORY["fml40::ProvidesProductionData"] = ProvidesProductionData
DT_FACTORY["fml40::Harvests"] = Harvests
DT_FACTORY["fml40::Forwards"] = Forwards
DT_FACTORY["fml40::AcceptsForwardingJobs"] = AcceptsForwardingJobs
DT_FACTORY["fml40::ProvidesPassabilityInformation"] = ProvidesPassabilityInformation
DT_FACTORY["fml40::ProvidesMoisturePrediction"] = ProvidesMoisturePrediction
DT_FACTORY["fml40::MoisturePredictionReport"] = MoisturePredictionReport
DT_FACTORY["fml40::AcceptsPassabilityReport"] = AcceptsPassabilityReport
DT_FACTORY["Thing"] = Thing
DT_FACTORY["ManagesJobs"] = ManagesJobs
DT_FACTORY["Location"] = Location
DT_FACTORY["Composite"] = Composite
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
def get_dt_names():
......@@ -106,6 +107,8 @@ def create_dt_with_idp(config, id_p):
# d_t = DT_FACTORY.get(dt_type, ManagingActor)(id_p, config)
# return d_t
###
#TODO: was passiert, wenn es unter subfeature noch ein subsubfeature gibt?
def build_sub_featrues(thing_ref, feature_proxy, json_feature):
json_sub_features = json_feature.get("subFeatures", [])
......@@ -126,6 +129,13 @@ def build_sub_featrues(thing_ref, feature_proxy, json_feature):
def build(thing_ref, attributes):
thing_proxy = thing_ref.proxy()
roles = attributes.get("roles", [])
if not roles:
APP_LOGGER.critical("Roles: %s is missing" % roles)
else:
APP_LOGGER.debug("Adding roles: %s" % roles)
thing_proxy.roles = roles
json_features = attributes.get("features", [])
for json_feature in json_features:
class_name = json_feature.get("class", "")
......@@ -153,17 +163,22 @@ def create_dt_ref(model, grant_type, secret, username, password, is_broker, is_r
:rtype: tuple(Reference, str)
"""
# id_p = get_idp(grant_type, thing_id, secret, username, password)
attributes = model.get("attributes", None)
if attributes is None:
print("Incomplete model: attributes missing!")
sys.exit()
sys.exit("Incomplete model: attributes missing!")
attributes = str(attributes).replace("fml40::", "").replace("ml40::", "").replace("'", '"')
attributes = json.loads(attributes)
thing_type = attributes.get("class", "")
if thing_type == "":
print("Unknown type %s" % thing_type)
sys.exit()
roles = attributes.get("roles", None)
if roles is None:
sys.exit("Incomplete model: roles missing!")
thing_name = attributes.get("name", "")
APP_LOGGER.debug("Creating ditigtal twin %s" % thing_name)
d_t = DT_FACTORY.get(thing_type, ManagingActor)
......@@ -174,7 +189,8 @@ def create_dt_ref(model, grant_type, secret, username, password, is_broker, is_r
username=username,
password=password,
is_broker=is_broker,
is_repo=is_repo,
is_repo=is_repo
)
build(thing_ref, attributes)
return thing_ref
from ml.managed_actor import ManagedActor
from ml.identifier import ID
import types
class Feature(ManagedActor):
def __init__(self, name, ref_managing_actor):
......
......@@ -16,7 +16,6 @@ def __init__(self, name, ref_managing_actor):
def from_json(self, json_obj):
super().from_json(json_obj)
def create_service_reply(self, json_body, results):
self.service_reply = ServiceReply()
thing_proxy = self.managing_actor
......
......@@ -16,10 +16,21 @@
from ml.tools import decode_message
from ml.tools import load_config
from ml.app_logger import APP_LOGGER
from ml.fml40.features.functionalities.forwards import send_passability_request
from ml.tools import create_request
class bcolors:
"""colors for the console log"""
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
class BaseVariable(object):
IDP_URL = "https://idp.s3i.vswf.dev/"
IDP_REALM = "KWH"
......@@ -37,15 +48,14 @@ def get_sensor_uuid(body_json):
class Thing(ManagingActor):
def __init__(
self,
client_secret,
model: dict,
grant_type: str,
is_broker: bool,
is_repo: bool,
username=None,
password=None,
endpoint=None,
self,
client_secret,
model: dict,
grant_type: str,
is_broker: bool,
is_repo: bool,
username=None,
password=None,
):
super(Thing, self).__init__()
self.__thing_id = model.get("thingId", "")
......@@ -54,32 +64,39 @@ def __init__(
self.__username = username
self.__password = password
self.__client_secret = client_secret
self.__all_endpoints = model.get("allEndpoints", "")
self.__is_broker = is_broker
self.__is_repo = is_repo
self.__access_token = ""
self.__endpoint = f"s3ib://{self.__thing_id}"
self.__endpoint = ""
self.__ws_connected = False
self.__observers = []
self._broker = None
self._ws = None
self.roles = []
self.features = {}
self.broker = None
self.ws = None
self.dir = None
attributes = model.get("attributes", None)
self.__name = ""
self.__class_name = ""
self.__type_name = ""
self.__represents = ""
self.__thing_structure = {}
self.__default_hmi = ""
self.roles = []
self.__features = {}
if attributes:
self.__name = attributes.get("name", "")
self.__class_name = attributes.get("class", "")
self.__type_name = attributes.get("type", "")
self.__represents = attributes.get("represents", "")
self.__thing_structure = attributes.get("thingStructure", {})
self.__default_hmi = attributes.get("default_hmi", "")
@property
def features(self):
return self.__features
@features.setter
def features(self, value):
self.__features = value
def send_message(self, receiver_ids, req):
send_message(self.__access_token, receiver_ids, req)
......@@ -94,11 +111,13 @@ def send_service_message(self, receiver_ids, service_class_name, parameters):
parameters,
)
"""
def on_receive(self, msg, decode=True):
# TODO: Invent a different mechanism for this. Works for now!
# APP_LOGGER.info(f"Receiving message: {message_type}")
body_str = decode_message(msg, decode)
body_json = json.loads(body_str)
print(body_json)
message_type = body_json.get("messageType", "")
if message_type == "serviceRequest":
self.on_service_request(body_json)
......@@ -108,12 +127,7 @@ def on_receive(self, msg, decode=True):
self.on_process_get_value_reply(body_json)
elif message_type == "serviceReply":
self.on_process_service_reply(body_json)
def on_process_service_reply(self, msg):
pass
def on_process_get_value_reply(self, body_json):
self.handle_humidity_get_value_request(body_json)
"""
@property
def class_name(self):
......@@ -139,26 +153,15 @@ def name(self):
def thing_id(self):
return self.__thing_id
def attach(self, observer):
if observer not in self.__observers:
self.__observers.append(observer)
def detach(self, observer):
if observer in self._observers:
self.__observers.remove(observer)
def notify(self, path, modifier=None):
for observer in self.__observers:
if modifier != observer:
observer.update(self, path)
def run_forever(self):
print("[S³I]: Launch {}{}{}".format(bcolors.OKGREEN, self.name, bcolors.ENDC))
self.__connect_with_idp()
def __on_key_pressed(self, key):
pass
def __connect_with_idp(self):
print(bcolors.OKBLUE + "[S³I][IdP]" + bcolors.ENDC + ": Connect with S3I-IdentityProvider")