Commit 316b2fbf authored by GromeTT's avatar GromeTT
Browse files

ENH: Added documentation for thing.py

parent 1be54e4b
"""This module implements the thing class which is the core element of
this package."""
import ast import ast
import threading import threading
import json import json
...@@ -61,9 +64,12 @@ def __init__( ...@@ -61,9 +64,12 @@ def __init__(
self.__ws_connected = False self.__ws_connected = False
self.broker = None self.broker = None
self.ws = None self.ws = None
# TODO: Change the variable name dir, because it is a builtin
# name.
self.dir = None self.dir = None
self.repo = None self.repo = None
# : Dict[<str>, <str>]
self.repo_json = dict() self.repo_json = dict()
self.dir_json = dict() self.dir_json = dict()
self.dt_json = dict() self.dt_json = dict()
...@@ -72,6 +78,7 @@ def __init__( ...@@ -72,6 +78,7 @@ def __init__(
self.__name = "" self.__name = ""
self.__roles = {} self.__roles = {}
self.__features = {} self.__features = {}
# ??? Is this property necessary? Only used as return value in _getValue()
self.__resGetValue = list() self.__resGetValue = list()
if attributes: if attributes:
self.__name = attributes.get("name", "") self.__name = attributes.get("name", "")
...@@ -100,6 +107,12 @@ def features(self): ...@@ -100,6 +107,12 @@ def features(self):
@features.setter @features.setter
def features(self, value): def features(self, value):
"""Replaces __features with vale.
:param value: New collection of features
"""
self.__features = value self.__features = value
@property @property
...@@ -188,6 +201,7 @@ def policy_id(self): ...@@ -188,6 +201,7 @@ def policy_id(self):
def run_forever(self): def run_forever(self):
"""Starts the thing in permanent mode. """Starts the thing in permanent mode.
""" """
# TODO: Use logger instead! # TODO: Use logger instead!
...@@ -201,6 +215,12 @@ def run_forever(self): ...@@ -201,6 +215,12 @@ def run_forever(self):
@staticmethod @staticmethod
def add_user_def(func): def add_user_def(func):
"""Runs func in a thread.
:param func: Function to be executed.
"""
threading.Thread(target=func).start() threading.Thread(target=func).start()
def __json_syn(self, freq=0.1): def __json_syn(self, freq=0.1):
...@@ -213,7 +233,7 @@ def __json_syn(self, freq=0.1): ...@@ -213,7 +233,7 @@ def __json_syn(self, freq=0.1):
continue continue
def __dir_syn(self, freq=0.1): def __dir_syn(self, freq=0.1):
"""Applies local changes to the directory entry. """Applies local changes to the directory entry in the cloud.
:param freq: Frequency of the update. :param freq: Frequency of the update.
""" """
...@@ -232,7 +252,7 @@ def __dir_syn(self, freq=0.1): ...@@ -232,7 +252,7 @@ def __dir_syn(self, freq=0.1):
# continue # continue
def __repo_syn(self, freq=0.1): def __repo_syn(self, freq=0.1):
"""Applies local changes to the repository entry. """Applies local changes to the repository entry in the cloud.
:param freq: Frequency of the update. :param freq: Frequency of the update.
""" """
...@@ -241,6 +261,7 @@ def __repo_syn(self, freq=0.1): ...@@ -241,6 +261,7 @@ def __repo_syn(self, freq=0.1):
time.sleep(freq) time.sleep(freq)
old_repo_json = self.repo_json old_repo_json = self.repo_json
self.to_repo_json() self.to_repo_json()
# TODO: Clean up this reqion
if self.repo_json == old_repo_json: if self.repo_json == old_repo_json:
continue continue
else: else:
...@@ -251,7 +272,9 @@ def __repo_syn(self, freq=0.1): ...@@ -251,7 +272,9 @@ def __repo_syn(self, freq=0.1):
continue continue
def __connect_with_idp(self): def __connect_with_idp(self):
""" """Establishes a connection to the identity provider which guarantees,
that the java web token needed to use s3i online services will
be renewed if it has expired.
""" """
...@@ -276,6 +299,13 @@ def __connect_with_idp(self): ...@@ -276,6 +299,13 @@ def __connect_with_idp(self):
idp.run_forever(token_type=TokenType.ACCESS_TOKEN, on_new_token=self.__on_token) idp.run_forever(token_type=TokenType.ACCESS_TOKEN, on_new_token=self.__on_token)
def __on_token(self, token): def __on_token(self, token):
"""Updates the java web token with token and reestablishes connections
to the s3i online services.
:param token: New java web token
"""
self.__access_token = token self.__access_token = token
self.__connect_with_dir() self.__connect_with_dir()
self.__connect_with_repo() self.__connect_with_repo()
...@@ -283,6 +313,15 @@ def __on_token(self, token): ...@@ -283,6 +313,15 @@ def __on_token(self, token):
self.__connect_with_broker() self.__connect_with_broker()
def __connect_with_dir(self): def __connect_with_dir(self):
"""Initializes the property dir with a Directory object which can be
used to access the s3i directory online service.
:returns:
:rtype:
"""
# TODO: Use logger
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Dir]" + "[S³I][Dir]"
...@@ -294,6 +333,15 @@ def __connect_with_dir(self): ...@@ -294,6 +333,15 @@ def __connect_with_dir(self):
) )
def __connect_with_repo(self): def __connect_with_repo(self):
"""Initializes the property repo whit a Repository object which can be
used to access the s3i repository online service.
:returns:
:rtype:
"""
# TODO: Use logger
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Repo]" + "[S³I][Repo]"
...@@ -305,6 +353,13 @@ def __connect_with_repo(self): ...@@ -305,6 +353,13 @@ def __connect_with_repo(self):
) )
def __connect_with_broker(self): def __connect_with_broker(self):
"""Initializes the property broker with a Broker object. Additionally
a callback function is registered which handles incoming S3I-B
messages.
"""
# TODO: Use logger
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Broker]" + "[S³I][Broker]"
...@@ -348,6 +403,14 @@ def receive(): ...@@ -348,6 +403,14 @@ def receive():
).start() ).start()
def __on_broker_callback(self, ch, method, properties, body): def __on_broker_callback(self, ch, method, properties, body):
"""Parses body (content of a S3I-B message) and delegates the
processing of the message to a separate method. The method is
selected according to the message's type.
:param body: S3I-B message
"""
if isinstance(body, bytes): if isinstance(body, bytes):
body_str = body.decode('utf8').replace("'", '"') body_str = body.decode('utf8').replace("'", '"')
try: try:
...@@ -376,6 +439,12 @@ def __on_broker_callback(self, ch, method, properties, body): ...@@ -376,6 +439,12 @@ def __on_broker_callback(self, ch, method, properties, body):
pass pass
def on_user_message(self, msg): def on_user_message(self, msg):
"""Handles Prints msg to stdout.
:param msg: S3I-B message
"""
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Broker]" + "[S³I][Broker]"
...@@ -385,6 +454,13 @@ def on_user_message(self, msg): ...@@ -385,6 +454,13 @@ def on_user_message(self, msg):
) )
def on_get_value_request(self, msg): def on_get_value_request(self, msg):
"""Handles GetValueRequest message. Looks up the value specified in msg and
sends a GetValueReply message back to the sender.
:param msg: GetValueRequest
"""
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Broker]" + "[S³I][Broker]"
...@@ -438,6 +514,13 @@ def on_get_value_request(self, msg): ...@@ -438,6 +514,13 @@ def on_get_value_request(self, msg):
+ res.text) + res.text)
def _uriToData(self, uri): def _uriToData(self, uri):
"""Returns a copy of the value found at uri.
:param uri: Path to value
:rtype: Feature
"""
if uri == "": if uri == "":
return self.dt_json return self.dt_json
else: else:
...@@ -462,6 +545,17 @@ def _uriToData(self, uri): ...@@ -462,6 +545,17 @@ def _uriToData(self, uri):
return response return response
def _getValue(self, source, uri_list): def _getValue(self, source, uri_list):
"""Searches for the value specified by uri_list in source and stores
the result in __resGetValue.
:param source: Object that is scanned
:param uri_list: List containing path
"""
# ??? What if the uri points to a Value object?
# Shouldn't it be serialized?!
value = source[uri_list[0]] value = source[uri_list[0]]
if uri_list.__len__() == 1: if uri_list.__len__() == 1:
# if is ditto-feature # if is ditto-feature
...@@ -477,6 +571,7 @@ def _getValue(self, source, uri_list): ...@@ -477,6 +571,7 @@ def _getValue(self, source, uri_list):
self.__resGetValue.append(value) self.__resGetValue.append(value)
return return
if isinstance(value, dict): if isinstance(value, dict):
# ??? uri_list.pop(0) better?!
del uri_list[0] del uri_list[0]
self._getValue(value, uri_list) self._getValue(value, uri_list)
if isinstance(value, list): if isinstance(value, list):
...@@ -513,6 +608,16 @@ def _getValue(self, source, uri_list): ...@@ -513,6 +608,16 @@ def _getValue(self, source, uri_list):
self.__resGetValue.append(value) self.__resGetValue.append(value)
def _findValue(self, json, value): def _findValue(self, json, value):
"""Returns true if value has been found in json, otherwise returns false.
:param json: dictionary
:param value:
:returns:
:rtype:
"""
# TODO: Simplify: value in json.values()
for item in json: for item in json:
if json[item] == value: if json[item] == value:
# print("Parameter: ", json[item]) # print("Parameter: ", json[item])
...@@ -520,6 +625,14 @@ def _findValue(self, json, value): ...@@ -520,6 +625,14 @@ def _findValue(self, json, value):
return False return False
def on_service_request(self, body_json): def on_service_request(self, body_json):
"""Handles ServiceRequest messages. Executes the method of the
functionality specified in body_json and send a ServiceReply
back to the sender.
:param body_json: ServiceRequest
"""
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Broker]" + "[S³I][Broker]"
...@@ -603,6 +716,14 @@ def on_service_request(self, body_json): ...@@ -603,6 +716,14 @@ def on_service_request(self, body_json):
+ res.text) + res.text)
def on_get_value_reply(self, msg): def on_get_value_reply(self, msg):
"""Handles GetValueReply messsage. Prints the content of msg to stdout.
:param msg: GetValueReply
"""
# ???: Behavior should be defined by the user! Maybe he want
# to process the result!
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Broker]" + "[S³I][Broker]"
...@@ -624,6 +745,12 @@ def on_get_value_reply(self, msg): ...@@ -624,6 +745,12 @@ def on_get_value_reply(self, msg):
) )
def on_service_reply(self, msg): def on_service_reply(self, msg):
"""Handles ServiceReply messages. Prints the content of msg to stdout.
:param msg: ServiceReply
"""
print( print(
BColors.OKBLUE BColors.OKBLUE
+ "[S³I][Broker]" + "[S³I][Broker]"
...@@ -645,6 +772,13 @@ def on_service_reply(self, msg): ...@@ -645,6 +772,13 @@ def on_service_reply(self, msg):
) )
def to_dir_json(self): def to_dir_json(self):
"""Returns a dictionary representing this thing's directory entry.
:returns: Directory representation of this object
:rtype: dict
"""
self.dir_json = self.dir.queryThingIDBased(self.thing_id) self.dir_json = self.dir.queryThingIDBased(self.thing_id)
if self.thing_id is not None: if self.thing_id is not None:
self.dir_json["thingId"] = self.thing_id self.dir_json["thingId"] = self.thing_id
...@@ -684,10 +818,24 @@ def to_dir_json(self): ...@@ -684,10 +818,24 @@ def to_dir_json(self):
return self.dir_json return self.dir_json
def to_repo_json(self): def to_repo_json(self):
"""Returns a dictionary representing this thing's repository entry.
:returns: Repository representation of this object
:rtype: dict
"""
self.repo_json = self.dt_json self.repo_json = self.dt_json
return self.repo_json return self.repo_json
def to_json(self): def to_json(self):
"""Returns a dictionary representing this thing in it's current state.
:returns: Representation of this object
:rtype: dict
"""
self.dt_json = { self.dt_json = {
"thingId": self.thing_id, "thingId": self.thing_id,
"policyId": self.policy_id, "policyId": self.policy_id,
...@@ -707,6 +855,13 @@ def to_json(self): ...@@ -707,6 +855,13 @@ def to_json(self):
return self.dt_json return self.dt_json
def to_subthing_json(self): def to_subthing_json(self):
"""
:returns:
:rtype:
"""
json_out = { json_out = {
"class": "ml40::Thing", "class": "ml40::Thing",
"identifier": self.thing_id, "identifier": self.thing_id,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment