Skip to content

Instantly share code, notes, and snippets.

@manchoz
Created November 15, 2017 10:22
Show Gist options
  • Save manchoz/8b0c859fb502074c420ffb2f0025cf56 to your computer and use it in GitHub Desktop.
Save manchoz/8b0c859fb502074c420ffb2f0025cf56 to your computer and use it in GitHub Desktop.
Use ctypes and some python magic to unpack C/C++ bitfields struct dynamically.
typedef struct __attribute__ ((packed)) Data {
uint32_t temperature_internal: 10;
uint32_t temperature: 10;
uint32_t pressure: 12;
uint32_t humidity: 10;
uint32_t temperature_soil: 10;
uint32_t battery_level: 7;
uint32_t leaf_wetness: 4;
uint32_t pad0: 1;
uint32_t rainrate: 8;
uint32_t pad1: 24;
} data_t;
import binascii
import json
import pprint
from ctypes import c_uint32, LittleEndianStructure
def ctypes_unpack(fields, data):
def _get_fields():
return fields
class Frame(LittleEndianStructure):
_fields_ = _get_fields()
def __init__(self, _):
super().__init__()
def __new__(cls, buf=None):
return cls.from_buffer_copy(buf)
def _to_dict(self):
return {field[0]: getattr(self, field[0]) for field in self._fields_}
@property
def fields(self):
return self._to_dict()
frame = Frame(data)
return frame.fields
def main():
with open('sensors.json') as f:
result = json.loads(f.read())
fields = [(k, eval(v['type']), v['bits']) for k, v in result.items()]
# frame = decode(fields, binascii.unhexlify('f514d570c7e5923feb000000'))
frame = ctypes_unpack(fields, binascii.unhexlify('fa3025e4e8f4f21b75000000'))
pprint.pprint(frame)
if __name__ == '__main__':
main()
{
"temperature_internal": { "type": "c_uint32", "bits": 10, "max": 50, "min": -30},
"temperature": { "type": "c_uint32", "bits": 10, "max": 50, "min": -30},
"pressure": { "type": "c_uint32", "bits": 12, "max": 1100, "min": 800},
"humidity": { "type": "c_uint32", "bits": 10, "max": 100, "min": 0},
"temperature_soil": { "type": "c_uint32", "bits": 10, "max": 50, "min": -30},
"battery_level": { "type": "c_uint32", "bits": 7, "max": 12, "min": 0},
"leaf_wetness": { "type": "c_uint32", "bits": 4, "max": 15, "min": 0},
"rainrate": { "type": "c_uint32", "bits": 8, "max": 255, "min": 0}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment