diff --git a/src/combined.py b/src/combined.py index 10a3719..b3be277 100644 --- a/src/combined.py +++ b/src/combined.py @@ -15,16 +15,12 @@ OpenThings.init(Devices.CRYPT_PID) PURPLE_ID = 0x68B # captured from a real device using Monitor.py -m = OpenThings.alterMessage( ####HERE use the new Message() abstraction - Devices.create_message(Devices.SWITCH), - header_sensorid=PURPLE_ID, - recs_0_value=1) +m = OpenThings.Message(Devices.SWITCH) +m.set(header_sensorid=PURPLE_ID, recs_SWITCH_STATE_value=1) purple_on = OpenThings.encode(m) -m = OpenThings.alterMessage( ####HERE use the new Message() abstraction - Devices.create_message(Devices.SWITCH), - header_sensorid=PURPLE_ID, - recs_0_value=0) +m = OpenThings.Message(Devices.SWITCH) +m.set(header_sensorid=PURPLE_ID, recs_SWITCH_STATE_value=0) purple_off = OpenThings.encode(m) # build OOK messages for legacy green button diff --git a/src/energenie/Devices.py b/src/energenie/Devices.py index 939570c..2fa374f 100644 --- a/src/energenie/Devices.py +++ b/src/energenie/Devices.py @@ -220,10 +220,10 @@ def send_join_ack(radio, mfrid, productid, sensorid): # send back a JOIN ACK, so that join light stops flashing - response = OpenThings.alterMessage(create_message(JOIN_ACK), ####HERE use the new Message() - header_mfrid=mfrid, - header_productid=productid, - header_sensorid=sensorid) + response = OpenThings.Message(JOIN_ACK) + response.set(header_mfrid=mfrid, + header_productid=productid, + header_sensorid=sensorid) p = OpenThings.encode(response) radio.transmitter() radio.transmit(p, inner_times=2) @@ -317,7 +317,7 @@ return "LegacyDevice(%s)" % str(self.device_id) def send_message(self, payload): - ####HERE#### interface with air_interface + #TODO: interface with air_interface # Encode the payload two bits per byte as per OOK spec #TODO, should we just pass a payload (as a pydict or tuple) to the air_interface adaptor #and let it encode it, to be consistent with the FSK MiHome devices? @@ -363,7 +363,7 @@ self.send_message("join ack") # TODO def incoming_message(self, payload): - ####HERE#### interface with air_interface + #TODO: interface with air_interface """Handle incoming messages for this device""" #NOTE: we must have already decoded the message with OpenThings to be able to get the addresses out # so payload at this point must be a pydict? @@ -378,7 +378,7 @@ raise RuntimeError("Method unimplemented") #TODO def send_message(self, payload): - ####HERE#### interface with air_interface + #TODO: interface with air_interface #is payload a pydict with header at this point, and we have to call OpenThings.encode? #should the encode be done here, or in the air_interface adaptor? @@ -481,21 +481,19 @@ return self.readings def turn_on(self): - #TODO: header construction should be in MiHomeDevice as it is shared - payload = OpenThings.alterMessage( ####HERE use the new Message() - create_message(SWITCH), - header_productid = self.product_id, - header_sensorid = self.device_id, - recs_0_value = True) + #TODO: header construction should be in MiHomeDevice as it is shared? + payload = OpenThings.Message(SWITCH) + payload.set(header_productid=self.product_id, + header_sensorid=self.device_id, + recs_SWITCH_STATE_value=True) self.send_message(payload) def turn_off(self): - #TODO: header construction should be in MiHomeDevice as it is shared - payload = OpenThings.alterMessage( ####HERE use the new Message() - create_message(SWITCH), - header_productid = self.product_id, - header_sensorid = self.device_id, - recs_0_value = False) + #TODO: header construction should be in MiHomeDevice as it is shared? + payload = OpenThings.Message(SWITCH) + payload.set(header_productid=self.product_id, + header_sensorid=self.device_id, + recs_SWITCH_STATE_value=False) self.send_message(payload) #TODO: difference between 'is on and 'is requested on' diff --git a/src/energenie/OnAir.py b/src/energenie/OnAir.py index 7a5612b..560df00 100644 --- a/src/energenie/OnAir.py +++ b/src/energenie/OnAir.py @@ -17,6 +17,7 @@ import OpenThings import TwoBit import radio +import time class OpenThingsAirInterface(): @@ -69,7 +70,8 @@ while True: # timer not expired if radio.is_receive_waiting(): payload = radio.receive() # TODO payload, radio_measurements = radio.receive() - p = OpenThings.decode(payload) + now = time.time() + p = OpenThings.decode(payload, receive_timestamp=now) #TODO: if crc failure, report it, but keep trying #if crc check passes... break diff --git a/src/energenie/OpenThings.py b/src/energenie/OpenThings.py index 9decbdd..54924c6 100644 --- a/src/energenie/OpenThings.py +++ b/src/energenie/OpenThings.py @@ -155,7 +155,7 @@ #we're trying to process an encrypted packet without decrypting it. #the code should be more robust to this (by checking the CRC) -def decode(payload, decrypt=True): +def decode(payload, decrypt=True, receive_timestamp=None): """Decode a raw buffer into an OpenThings pydict""" #Note, decrypt must already have run on this for it to work length = payload[0] @@ -250,11 +250,14 @@ # store rec recs.append(rec) - return { + m = { "type": "OK", "header": header, "recs": recs } + if receive_timestamp != None: + m["rxtimestamp"] = receive_timestamp + return Message(m) #----- MESSAGE ENCODER -------------------------------------------------------- diff --git a/src/energenie/Registry_test.py b/src/energenie/Registry_test.py index 5ae00f1..29df23c 100644 --- a/src/energenie/Registry_test.py +++ b/src/energenie/Registry_test.py @@ -59,16 +59,13 @@ ## poor mans incoming synthetic message - report = Devices.create_message(Devices.MIHO005_REPORT) - report = OpenThings.alterMessage( ####HERE - report, - recs_0_value=240, # voltage - recs_1_value=2, # current - recs_2_value=50, # frequency - recs_3_value=100, # real power - recs_4_value=0, # reactive power - recs_5_value=100, # apparent power - ) + report = OpenThings.Message(Devices.MIHO005_REPORT) + report.set(recs_VOLTAGE_value=240, + recs_CURRENT_value=2, + recs_FREQUENCY_value=50, + recs_REAL_POWER_value=100, + recs_REACTIVE_POWER_value=0, + recs_APPARENT_POWER_value=100) self.tv.incoming_message(report) # get readings from device diff --git a/src/monitor.py b/src/monitor.py index edb8351..d53c73d 100644 --- a/src/monitor.py +++ b/src/monitor.py @@ -33,14 +33,16 @@ if radio.is_receive_waiting(): trace("receiving payload") payload = radio.receive() + now = time.time() try: - decoded = OpenThings.decode(payload) - now = time.time() + decoded = OpenThings.decode(payload, receive_timestamp=now) except OpenThings.OpenThingsException as e: warning("Can't decode payload:" + str(e)) continue - - OpenThings.showMessage(decoded, timestamp=now) ####HERE msg.dump() + + #TODO: Consider putting a 'timestamp' in a received decoded message + print(now) #TODO: improve formatting of timestamp + print(decoded) # Any device that reports will be added to the non-persistent directory Registry.update(decoded) ##trace(decoded) @@ -52,10 +54,11 @@ print("Empty record:%s" % decoded) else: # assume only 1 rec in a join, for now + #TODO: 'if OpenThings.PARAM_JOIN in decoded:' - special magic handling for param_id if decoded["recs"][0]["paramid"] == OpenThings.PARAM_JOIN: - mfrid = OpenThings.getFromMessage(decoded, "header_mfrid") ####HERE use the new Message() - productid = OpenThings.getFromMessage(decoded, "header_productid") ####HERE use the new Message() - sensorid = OpenThings.getFromMessage(decoded, "header_sensorid") ####HERE use the new Message() + mfrid = decoded.get("header_mfrid") + productid = decoded.get("header_productid") + sensorid = decoded.get("header_sensorid") Devices.send_join_ack(radio, mfrid, productid, sensorid) diff --git a/src/switch.py b/src/switch.py index fa9e7e5..80aa693 100644 --- a/src/switch.py +++ b/src/switch.py @@ -38,14 +38,15 @@ if radio.is_receive_waiting(): ##trace("receiving payload") payload = radio.receive() + now = time.time() try: - decoded = OpenThings.decode(payload) - now = time.time() + decoded = OpenThings.decode(payload, receive_timestamp=now) except OpenThings.OpenThingsException as e: warning("Can't decode payload:" + str(e)) return - OpenThings.showMessage(decoded, timestamp=now) ##HERE msg.dump() + print(now) #TODO: better timestamp handling + decoded.dump() # Any device that reports will be added to the non-persistent directory Registry.update(decoded) ##trace(decoded) @@ -57,9 +58,9 @@ else: # assume only 1 rec in a join, for now if decoded["recs"][0]["paramid"] == OpenThings.PARAM_JOIN: - mfrid = OpenThings.getFromMessage(decoded, "header_mfrid") ####HERE use the new Message() - productid = OpenThings.getFromMessage(decoded, "header_productid") ####HERE use the new Message() - sensorid = OpenThings.getFromMessage(decoded, "header_sensorid") ####HERE use the new Message() + mfrid = decoded.get("header_mfrid") + productid = decoded.get("header_productid") + sensorid = decoded.get("header_sensorid") Devices.send_join_ack(radio, mfrid, productid, sensorid) @@ -79,9 +80,8 @@ productid = header["productid"] if Devices.hasSwitch(mfrid, productid): - request = OpenThings.alterMessage(Devices.create_message(Devices.SWITCH), ####HERE use the new Message() - header_sensorid=sensorid, - recs_0_value=switch_state) + request = OpenThings.Message(Devices.SWITCH) + request.set(header_sensorid=sensorid, recs_SWITCH_STATE_value=switch_state) p = OpenThings.encode(request) print("Sending switch message to %s %s" % (hex(productid), hex(sensorid))) # Transmit multiple times, hope one of them gets through @@ -99,10 +99,10 @@ # Seed the registry with a known device, to simplify tx-only testing SENSOR_ID = 0x68B # captured from a real device - device_header = OpenThings.alterMessage(Devices.create_message(Devices.REGISTERED_SENSOR), ####HERE use the new Message() - header_mfrid = Devices.MFRID, - header_productid = Devices.PRODUCTID_MIHO005, # adaptor plus - header_sensorid = SENSOR_ID) + device_header = OpenThings.Message(header_mfrid=Devices.MFRID, + header_productid=Devices.PRODUCTID_MIHO005, + header_sensorid=SENSOR_ID, + recs=[]) Registry.update(device_header)