import struct
from typing import Tuple
import arrow
from ..base import Component
from .base import SensorBase
[docs]class APDS9300Sensor(SensorBase):
type = 0x0B
[docs] class Config(SensorBase.Config):
def __init__(self, *, interval, address=None):
super().__init__(interval)
self.address = address if address is not None else 0b0111001
[docs] def to_config_dict(self):
cfg = super().to_config_dict()
cfg[0x11] = struct.pack('B', self.address)
return cfg
[docs] @classmethod
def params_from_config_dict(cls, cfg):
return dict(address=struct.unpack('B', cfg.get(0x11, None))[0],
**SensorBase.Config.params_from_config_dict(cfg))
def __repr_fields__(self):
return dict(address=self.address, **super().__repr_fields__())
[docs] class MeasurementEvent(SensorBase.MeasurementEvent):
[docs] def parse(self):
super().parse()
self.raw: Tuple[int, int] = self.measurement_data if not self.error else (None, None)
@property
def lux(self):
if self.raw != (None, None):
return APDS9300Sensor.raw_to_lux(self.raw)
else:
return None
def __repr_fields__(self):
return dict(time=self.timestamp, raw=self.raw, error=self.error, lux=self.lux)
[docs] class State(Component.State):
def __init__(self, raw=(None, None), error=None, timestamp=None):
self.raw = raw
self.error = error
self.timestamp = timestamp
[docs] def update_from_bytes(self, data):
self.raw = APDS9300Sensor.parse_measurement_data(data)
self.error = None
self.timestamp = arrow.now()
[docs] def update_from_error(self, error_code, data):
self.raw = (None, None)
self.error = error_code
[docs] def update_from_event(self, event):
if isinstance(event, APDS9300Sensor.MeasurementEvent):
self.timestamp = event.timestamp
if event.error:
self.error = event.error
self.raw = (None, None)
else:
self.error = None
self.raw = event.measurement_data
@property
def lux(self):
if self.raw != (None, None):
return APDS9300Sensor.raw_to_lux(self.raw)
else:
return None
def __repr_fields__(self):
return dict(raw=self.raw, error=self.error, timestamp=self.timestamp, lux=self.lux)
[docs] @classmethod
def parse_measurement_data(cls, data):
return struct.unpack('<HH', data)
[docs] @classmethod
def raw_to_lux(cls, raw):
ch0, ch1 = raw
if ch0 == 0:
return 0.0
ch1_ch0 = ch1 / ch0
if ch1_ch0 <= 0.52:
return (0.0315 * ch0) - (0.0593 * ch0 * (ch1_ch0**1.4))
elif ch1_ch0 <= 0.65:
return (0.0229 * ch0) - (0.0291 * ch1)
elif ch1_ch0 <= 0.80:
return (0.0157 * ch0) - (0.0180 * ch1)
elif ch1_ch0 <= 1.3:
return (0.00338 * ch0) - (0.00260 * ch1)
else:
return 0.0