diff --git a/src/energenie/OpenThings.py b/src/energenie/OpenThings.py index 828a280..08a64da 100644 --- a/src/energenie/OpenThings.py +++ b/src/energenie/OpenThings.py @@ -2,6 +2,7 @@ # # Implement OpenThings message encoding and decoding +from lifecycle import * import time try: import crypto # python 2 @@ -641,10 +642,23 @@ ## msg.asdict() -> # pydict (for the encoder to use) ## +import copy + class Message(): - def __init__(self, pydict): + BLANK = { + "header": { + "mfrid" : None, + "productid": None, + "sensorid": None + } + } + + def __init__(self, pydict=None): + if pydict == None: + pydict = copy.deepcopy(Message.BLANK) self.pydict = pydict + @untested def __getitem__(self, key): try: # an integer key is used as a paramid in recs[] @@ -662,19 +676,80 @@ # just returns a reference to that part of the inner pydict return self.pydict[key] + @untested def copyof(self): # -> Message """Clone, to create a new message that is a completely independent copy""" import copy return Message(copy.deepcopy(self.pydict)) - #def __str__(self): # -> str - # pass ##TODO: replaces showMessage - # showMessage(self.pydict) ##TODO: Migrate code into this method + def __str__(self): # -> str + return "Message.STR" + def __repr__(self): # -> str + return "Message.REPR" + + @untested def dump(self): - showMessage(self.pydict) + msg = self.pydict + timestamp = None + + # TIMESTAMP + if timestamp != None: + print("receive-time:%s" % time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp))) + + # HEADER + if "header" in msg: + header = msg["header"] + mfrid = header["mfrid"] + if mfrid == None: mfrid = "" + else: mfrid = str(hex(mfrid)) + + productid = header["productid"] + if productid == None: productid = "" + else: productid = str(hex(productid)) + + sensorid = header["sensorid"] + if sensorid == None: sensorid = "" + else: sensorid = str(hex(sensorid)) + + print("mfrid:%s prodid:%s sensorid:%s" % (mfrid, productid, sensorid)) + + # RECORDS + if "recs" in msg: + for rec in msg["recs"]: + wr = rec["wr"] + if wr == True: + write = "write" + else: + write = "read " + + try: + paramname = rec["paramname"] # This only come out from decoded messages + except: + paramname = "" + + try: + paramid = rec["paramid"] #This is only present on a input message (e.g SWITCH) + paramname = paramid_to_paramname(paramid) + paramid = str(hex(paramid)) + except: + paramid = "" + + try: + paramunit = rec["paramunit"] # This only come out from decoded messages + except: + paramunit = "" + + if "value" in rec: + value = rec["value"] + else: + value = None + + print("%s %s %s %s = %s" % (write, paramid, paramname, paramunit, str(value))) + +@deprecated def showMessage(msg, timestamp=None): """Show the message in a friendly format""" @@ -725,6 +800,7 @@ # recs_0_value msg["recs"][0]["value"] # recs_WATER_DETECTOR_value msg["recs"].find_param("WATER_DETECTOR")["value"] +@deprecated def alterMessage(message, **kwargs): """Change parameters in-place in a message template""" @@ -749,6 +825,7 @@ return message +@deprecated def getFromMessage(message, keypath): """Get a field from a message, given an underscored keypath to the item""" path = keypath.split("_") @@ -761,13 +838,5 @@ message = message[pkey] return message[path[-1]] -# QUICK TEST - -if __name__ == "__main__": - import Devices - msg = Message(Devices.MIHO005_REPORT) - #print(str(msg)) - #msg.dump() - print(msg[PARAM_SWITCH_STATE]) # END diff --git a/src/energenie/OpenThings_test.py b/src/energenie/OpenThings_test.py index 958e627..554617c 100644 --- a/src/energenie/OpenThings_test.py +++ b/src/energenie/OpenThings_test.py @@ -7,6 +7,7 @@ from OpenThings import * import pprint +import unittest def printhex(payload): @@ -130,10 +131,109 @@ # FLOAT +#----- UNIT TEST FOR MESSAGE -------------------------------------------------- + +import Devices + +class TestMessage(unittest.TestCase): + def test_blank(self): + # create a blank message + msg = Message() + msg.dump() + + def XXXtest_blank_create_header(self): + # create a blank message and add some header fields at creation time + msg = Message(header_mfrid=123, header_productid=456, header_sensorid=789) + msg.dump() + + def XXXtest_add_header_dict(self): + # add header fields to a message after creation like a pydict + msg = Message() + msg["header"]["mfrid"] = 123 + msg.dump() + + def XXXtest_add_rec_dict(self): + # add rec fields to a message after creation like a pydict + msg = Message() + msg["recs"][0] = {"paramid": PARAM_SWITCH_STATE, "value": 1} + msg.dump() + + def XXXtest_add_header_path(self): + # add header fields to a message after creation via pathed keys + msg = Message() + msg.add(header_mfrid=123, header_productid=456) + msg.dump() + + def XXXtest_add_rec_path(self): + # add rec fields to a message after creation via pathed indexed keys + msg = Message() + msg.add(recs_0_paramid=PARAM_SWITCH_STATE, recs_0_value=1) + msg.dump() + + def XXXtest_add_rec_fn(self): + # add rec fields to a message after creation via pathed PARAM name keys + msg = Message() + msg.add_rec(PARAM_SWITCH_STATE, value=1) + msg.dump() + + def XXXtest_create_template(self): + # create a message from a template + msg = Message(Devices.MIHO005_REPORT) + msg.dump() + + def XXXtest_alter_rec_template(self): + # alter rec fields in a template + msg = Message(Devices.MIHO005_REPORT) + msg.alter(header_productid=123) + msg.alter(recs_SWITCH_STATE_value=1) + msg.dump() + + def XXXtest_dump(self): + ## dump a message in printable format + msg = Message(Devices.MIHO005_REPORT) + print(msg) + print(str(msg)) + + def XXXtest_pydict_read(self): + ## access a specific keyed entry like a normal pydict, for read + msg = Message(Devices.MIHO005_REPORT) + print(msg["header"]) + print(msg["header"]["mfrid"]) + + def XXXtest_pydict_write(self): + ## access a specific keyed entry like a normal pydict, for write + msg = Message(Devices.MIHO005_REPORT) + msg["header"]["mfrid"] = 222 + msg.dump() + + def XXXtest_paramid_read_struct(self): + # access a paramid entry for read of the whole structure + msg = Message(Devices.MIHO005_REPORT) + print(msg[PARAM_SWITCH_STATE]) + + def XXXtest_paramid_read_field(self): + ## read a value from a param id field that exists + msg = Message(Devices.MIHO005_REPORT) + print(msg[PARAM_SWITCH_STATE]["value"]) + + def XXXtest_paramid_write(self): + ## write a value to a param id field that exists + msg = Message(Devices.MIHO005_REPORT) + msg[PARAM_SWITCH_STATE]["value"] = 1 + msg.dump() + + +def test_message(): + import unittest + unittest.main() + if __name__ == "__main__": - #test_value_encoder() - #test_value_decoder() - test_payload_unencrypted() - #test_payload_encrypted() + ##TODO: Change these into unittest test cases + ##test_value_encoder() + ##test_value_decoder() + ##test_payload_unencrypted() + ##test_payload_encrypted() + + test_message() # END \ No newline at end of file