Skip to content

partector_ble_decoder_std

PartectorBleDecoderStd

Bases: PartectorBleDecoderBlueprint

Decode the std advertisement data from the Partector device.

Source code in src/naneos/partector_ble/decoder/partector_ble_decoder_std.py
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
class PartectorBleDecoderStd(PartectorBleDecoderBlueprint):
    """
    Decode the std advertisement data from the Partector device.
    """

    OFFSET_SERIAL_NUMBER = slice(14, 16)

    OFFSET_DEVICE_STATE_1 = slice(10, 12)
    ELEMET_DEVICE_STATE_2 = 19

    OFFSET_LDSA = slice(0, 3)
    OFFSET_AVERAGE_PARTICLE_DIAMETER = slice(3, 5)
    OFFSET_PARTICLE_NUMBER = slice(5, 8)
    OFFSET_TEMPERATURE = slice(8, 9)
    OFFSET_RELATIVE_HUMIDITY = slice(9, 10)
    OFFSET_BATTERY_VOLTAGE = slice(12, 14)
    OFFSET_PARTICLE_MASS = slice(14, 18)

    FACTOR_LDSA = 0.01
    FACTOR_BATTERY_VOLTAGE = 0.01
    FACTOR_PARTICLE_MASS = 0.01

    # == External used methods =====================================================================
    @classmethod
    def get_serial_number(cls, data: bytes) -> int:
        """
        Get the serial number from the advertisement data.
        """
        return int.from_bytes(data[cls.OFFSET_SERIAL_NUMBER], byteorder="little")

    @classmethod
    def decode(
        cls, data: bytes, data_structure: Optional[NaneosDeviceDataPoint] = None
    ) -> NaneosDeviceDataPoint:
        """
        Decode the advertisement data from the Partector device.
        """
        decoded_data = NaneosDeviceDataPoint(
            serial_number=cls.get_serial_number(data),
            ldsa=cls._get_ldsa(data),
            average_particle_diameter=cls._get_diameter(data),
            particle_number_concentration=cls._get_particle_number(data),
            temperature=cls._get_temperature(data),
            relative_humidity=cls._get_relative_humidity(data),
            device_status=cls._get_device_state(data),
            battery_voltage=cls._get_battery_voltage(data),
            particle_mass=cls._get_particle_mass(data),
        )

        if not data_structure:
            return decoded_data

        # Fill the given data_structure with the decoded data
        for field in NaneosDeviceDataPoint.BLE_STD_FIELD_NAMES:
            setattr(data_structure, field, getattr(decoded_data, field))
        return data_structure

    # == Helpers ===================================================================================
    @classmethod
    def _get_ldsa(cls, data: bytes) -> float:
        """
        Get the LDSA from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_LDSA], byteorder="little"))
        return val * cls.FACTOR_LDSA

    @classmethod
    def _get_diameter(cls, data: bytes) -> float:
        """
        Get the particle diameter from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_AVERAGE_PARTICLE_DIAMETER], byteorder="little"))
        return val

    @classmethod
    def _get_particle_number(cls, data: bytes) -> float:
        """
        Get the particle number from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_PARTICLE_NUMBER], byteorder="little"))
        return val

    @classmethod
    def _get_temperature(cls, data: bytes) -> float:
        """
        Get the temperature from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_TEMPERATURE], byteorder="little"))
        return val

    @classmethod
    def _get_relative_humidity(cls, data: bytes) -> float:
        """
        Get the relative humidity from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_RELATIVE_HUMIDITY], byteorder="little"))
        return val

    @classmethod
    def _get_device_state(cls, data: bytes) -> int:
        """
        Get the device state from the advertisement data.
        """
        val = int.from_bytes(data[cls.OFFSET_DEVICE_STATE_1], byteorder="little")
        val += ((int(data[cls.ELEMET_DEVICE_STATE_2]) >> 1) & 0b01111111) << 16
        return val

    @classmethod
    def _get_battery_voltage(cls, data: bytes) -> float:
        """
        Get the battery voltage from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_BATTERY_VOLTAGE], byteorder="little"))
        return val * cls.FACTOR_BATTERY_VOLTAGE

    @classmethod
    def _get_particle_mass(cls, data: bytes) -> float:
        """
        Get the particle mass from the advertisement data.
        """
        val = float(int.from_bytes(data[cls.OFFSET_PARTICLE_MASS], byteorder="little"))
        return val * cls.FACTOR_PARTICLE_MASS

decode(data, data_structure=None) classmethod

Decode the advertisement data from the Partector device.

Source code in src/naneos/partector_ble/decoder/partector_ble_decoder_std.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@classmethod
def decode(
    cls, data: bytes, data_structure: Optional[NaneosDeviceDataPoint] = None
) -> NaneosDeviceDataPoint:
    """
    Decode the advertisement data from the Partector device.
    """
    decoded_data = NaneosDeviceDataPoint(
        serial_number=cls.get_serial_number(data),
        ldsa=cls._get_ldsa(data),
        average_particle_diameter=cls._get_diameter(data),
        particle_number_concentration=cls._get_particle_number(data),
        temperature=cls._get_temperature(data),
        relative_humidity=cls._get_relative_humidity(data),
        device_status=cls._get_device_state(data),
        battery_voltage=cls._get_battery_voltage(data),
        particle_mass=cls._get_particle_mass(data),
    )

    if not data_structure:
        return decoded_data

    # Fill the given data_structure with the decoded data
    for field in NaneosDeviceDataPoint.BLE_STD_FIELD_NAMES:
        setattr(data_structure, field, getattr(decoded_data, field))
    return data_structure

get_serial_number(data) classmethod

Get the serial number from the advertisement data.

Source code in src/naneos/partector_ble/decoder/partector_ble_decoder_std.py
32
33
34
35
36
37
@classmethod
def get_serial_number(cls, data: bytes) -> int:
    """
    Get the serial number from the advertisement data.
    """
    return int.from_bytes(data[cls.OFFSET_SERIAL_NUMBER], byteorder="little")