Skip to content

Instantly share code, notes, and snippets.

@Lucianovici
Last active February 26, 2019 11:27
Show Gist options
  • Save Lucianovici/3851b1860da78ea60b4069305e6b0a39 to your computer and use it in GitHub Desktop.
Save Lucianovici/3851b1860da78ea60b4069305e6b0a39 to your computer and use it in GitHub Desktop.
Echo Payload API point - deserializer
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