Last active
February 26, 2019 11:27
-
-
Save Lucianovici/3851b1860da78ea60b4069305e6b0a39 to your computer and use it in GitHub Desktop.
Echo Payload API point - deserializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DevicePayloadView(APIView): | |
SUBMETER_TYPE = 1 | |
CONCENTRATOR_TYPE = 2 | |
authentication_classes = () | |
permission_classes = () | |
def post(self, request, eui): | |
""" | |
Proof of concept POST API point, to help Vali deserialize the binary payload. | |
Payload params: | |
EUI - 4 bytes - the unique ID of the device, provisioned in factory for each device. | |
type - 1 byte - device type. Sub-Meter = 1, Concentrator = 2. | |
timestamp - 4 bytes - the Epoch timestamp NTP synced. | |
delta - 2 bytes - the aggregation period in seconds. (usually around 60 seconds). | |
unit- 3 bytes - sensor unit tag. | |
""" | |
if not isinstance(request.body, bytes): | |
raise APIException(detail="Binary body expected", code=400) | |
body = bytearray(request.body) | |
device_eui = int.from_bytes(body[0:4], byteorder='big', signed=False) | |
device_type = int.from_bytes(body[4:5], byteorder='big', signed=False) | |
timestamp = int.from_bytes(body[5:9], byteorder='big', signed=False) | |
delta = int.from_bytes(body[9:11], byteorder='big', signed=False) | |
unit = int.from_bytes(body[11:14], byteorder='big', signed=False) | |
response_dict = { | |
'EUI': "RED{}".format(device_eui), | |
'type': device_type, | |
'timestamp': timestamp, | |
'data': { | |
'unit': unit, | |
'delta': delta, | |
'aggregated': self.getAggregatedDictFor(body, device_type), | |
'debug': {}, | |
'samples': [] | |
}, | |
'body': body.hex(), | |
} | |
service = AWSIoTMQTTService() | |
service.publish_device_processed_payload_to( | |
response_dict.get('EUI'), response_dict.get('data'), 'dCVX3RgiYQOOCglK' | |
) | |
return Response(response_dict) | |
def getAggregatedDictFor(self, body, device_type): | |
if device_type == self.SUBMETER_TYPE: | |
return self.get_submeter_aggregated_dict_for(body) | |
elif device_type == self.CONCENTRATOR_TYPE: | |
return self.get_concentrator_aggregated_dict_for(body) | |
return {} | |
def get_submeter_aggregated_dict_for(self, body): | |
""" | |
Energy - 4 bytes - the energy used or produced for all phases, measured in Wh. | |
Phase R Average Power - 4 bytes - the average power on phase R, measured in W. | |
Phase S Average Power - 4 bytes - the average power on phase S, measured in W. | |
Phase T Average Power - 4 bytes - the average power on phase S, measured in W. | |
IMPORTANT: All these parameters are computed from the last successfully sent payload! | |
""" | |
energy = int.from_bytes(body[14:18], byteorder='big', signed=True) / 100 | |
power_R = int.from_bytes(body[18:22], byteorder='big', signed=True) / 100 | |
power_S = int.from_bytes(body[22:26], byteorder='big', signed=True) / 100 | |
power_T = int.from_bytes(body[26:30], byteorder='big', signed=True) / 100 | |
return { | |
'energy': energy, | |
'power_R': power_R, | |
'power_S': power_S, | |
'power_T': power_T, | |
} | |
def get_concentrator_aggregated_dict_for(self, body): | |
param1B20 = int.from_bytes(body[14:22], byteorder='big', signed=True) / 100 | |
param1B24 = int.from_bytes(body[22:30], byteorder='big', signed=True) / 100 | |
param1B28 = int.from_bytes(body[30:38], byteorder='big', signed=True) / 100 | |
param1B2C = int.from_bytes(body[38:46], byteorder='big', signed=True) / 100 | |
param1B30 = int.from_bytes(body[46:54], byteorder='big', signed=True) / 100 | |
param0002 = int.from_bytes(body[54:58], byteorder='big', signed=True) / 100 | |
param0004 = int.from_bytes(body[58:62], byteorder='big', signed=True) / 100 | |
param0006 = int.from_bytes(body[62:66], byteorder='big', signed=True) / 100 | |
param0008 = int.from_bytes(body[66:70], byteorder='big', signed=True) / 10000 | |
param000A = int.from_bytes(body[70:74], byteorder='big', signed=True) / 10000 | |
param000C = int.from_bytes(body[74:78], byteorder='big', signed=True) / 10000 | |
param0048 = int.from_bytes(body[78:82], byteorder='big', signed=True) / 10000 | |
param0026 = int.from_bytes(body[82:86], byteorder='big', signed=True) / 10000 | |
param0028 = int.from_bytes(body[86:90], byteorder='big', signed=True) / 10000 | |
param002A = int.from_bytes(body[90:94], byteorder='big', signed=True) / 10000 | |
return { | |
'1B20': param1B20, | |
'1B24': param1B24, | |
'1B28': param1B28, | |
'1B2C': param1B2C, | |
'1B30': param1B30, | |
'0002': param0002, | |
'0004': param0004, | |
'0006': param0006, | |
'0008': param0008, | |
'000A': param000A, | |
'000C': param000C, | |
'0048': param0048, | |
'0026': param0026, | |
'0028': param0028, | |
'002A': param002A, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment