def __enter__(self) -> "MessageReader": logger.debug(f"open {self.path}") self.csv = self.path.open() reader = DictReader(self.csv) self.data = (row for row in reader if row["sensor"] == self.sensor.name) return self
def on_message(client, userdata, msg): try: data = Data.decode(msg.topic, msg.payload) except UserWarning as e: logger.debug(e) else: on_sensordata(data)
def __call__(self, *, raw: Optional[bool] = None): """Passive mode reading at regular intervals""" while self.serial.is_open: try: buffer = self._cmd("passive_read") try: obs = self.sensor.decode(buffer) except (SensorWarmingUp, InconsistentObservation) as e: logger.debug(e) time.sleep(5) except SensorWarning as e: logger.debug(e) self.serial.reset_input_buffer() else: yield RawData(obs.time, buffer) if raw else obs if self.samples: self.samples -= 1 if self.samples <= 0: break if self.interval: delay = self.interval - (time.time() - obs.time) if delay > 0: time.sleep(delay) except KeyboardInterrupt: print() break
def mock_reader__cmd(self, command: str) -> bytes: """bypass serial.write/read""" logger.debug(f"mock write/read: {command}") # nonlocal data if command == "passive_read": return next(data) if command in ["wake", "passive_mode"]: return b"." * sensor.command(command).answer_length return b""
def check(self, buffer: bytes, command: str) -> bool: """Validate buffer contents""" try: self.Message.decode(buffer, self.command(command)) except (WrongMessageFormat, WrongMessageChecksum) as e: logger.debug(f"decode error {e}") return False except (SensorWarmingUp, InconsistentObservation) as e: logger.debug(f"decode error {e}") return True else: return True
def __init__( self, sensor: str = "PMSx003", port: str = "/dev/ttyUSB0", interval: Optional[int] = None, samples: Optional[int] = None, ) -> None: """Configure serial port""" self.sensor = Sensor[sensor] self.serial = Serial() self.serial.port = port self.serial.baudrate = self.sensor.baud self.serial.timeout = 5 # max time to wake up sensor self.interval = interval self.samples = samples logger.debug(f"capture {samples if samples else '?'} {sensor} obs " f"from {port} every {interval if interval else '?'} secs")
def unpack(cls, message: bytes, header: bytes, length: int) -> Tuple[float, ...]: try: # validate full message msg = cls._validate(message, header, length) except WrongMessageFormat as e: # search last complete message on buffer start = message.rfind(header, 0, len(header) - length) if start < 0: # No match found raise # validate last complete message msg = cls._validate(message[start:start + length], header, length) # data: unpacked payload payload = cls._unpack(msg.payload) logger.debug(f"message payload: {payload}") return payload
def __init__( self, sensor: Union[Sensor, Supported, str] = Supported.default, port: str = "/dev/ttyUSB0", interval: Optional[int] = None, samples: Optional[int] = None, ) -> None: """Configure serial port""" self.sensor = sensor if isinstance(sensor, Sensor) else Sensor[sensor] self.pre_heat = self.sensor.pre_heat self.serial = Serial() self.serial.port = port self.serial.baudrate = self.sensor.baud self.serial.timeout = 5 # max time to wake up sensor self.interval = interval self.samples = samples logger.debug(f"capture {samples if samples else '?'} {sensor} obs " f"from {port} every {interval if interval else '?'} secs")
def csv( ctx: Context, capture: bool = Option(False, "--capture", help="write raw messages instead of observations"), overwrite: bool = Option(False, "--overwrite", help="overwrite file, if already exists"), path: Path = Argument(Path(), help="csv formatted file", show_default=False), ): """Read sensor and print measurements""" if path.is_dir(): # pragma: no cover path /= f"{datetime.now():%F}_pypms.csv" mode = "w" if overwrite else "a" logger.debug(f"open {path} on '{mode}' mode") with ctx.obj["reader"] as reader, path.open(mode) as csv: sensor_name = reader.sensor.name if not capture: logger.debug(f"capture {sensor_name} observations to {path}") # add header to new files if path.stat().st_size == 0: obs = next(reader()) csv.write(f"{obs:header}\n") for obs in reader(): csv.write(f"{obs:csv}\n") else: logger.debug(f"capture {sensor_name} messages to {path}") # add header to new files if path.stat().st_size == 0: csv.write("time,sensor,hex\n") for raw in reader(raw=True): csv.write(f"{raw.time},{sensor_name},{raw.hex}\n")
def __enter__(self) -> "SensorReader": """Open serial port and sensor setup""" if not self.serial.is_open: logger.debug(f"open {self.serial.port}") self.serial.open() self.serial.reset_input_buffer() # wake sensor and set passive mode logger.debug(f"wake {self.sensor}") buffer = self._cmd("wake") self._pre_heat() buffer += self._cmd("passive_mode") logger.debug(f"buffer length: {len(buffer)}") # check if the sensor answered if len(buffer) == 0: # pragma: no cover logger.error(f"Sensor did not respond, check UART pin connections") sys.exit(1) # check against sensor type derived from buffer if not self.sensor.check(buffer, "passive_mode"): # pragma: no cover logger.error(f"Sensor is not {self.sensor.name}") sys.exit(1) return self
def __enter__(self) -> "SensorReader": """Open serial port and sensor setup""" if not self.serial.is_open: logger.debug(f"open {self.serial.port}") self.serial.open() self.serial.reset_input_buffer() # wake sensor and set passive mode logger.debug(f"wake {self.sensor.name}") buffer = self._cmd("wake") + self._cmd("passive_mode") logger.debug(f"buffer length: {len(buffer)}") # check against sensor type derived from buffer if not self.sensor.check(buffer, "passive_mode"): logger.error(f"Sensor is not {self.sensor.name}") sys.exit(1) return self
def __exit__(self, exception_type, exception_value, traceback) -> None: logger.debug(f"close {self.path}") self.csv.close()
def __exit__(self, exception_type, exception_value, traceback) -> None: """Put sensor to sleep and close serial port""" logger.debug(f"sleep {self.sensor.name}") buffer = self._cmd("sleep") logger.debug(f"close {self.serial.port}") self.serial.close()
def __init__(self, message: bytes) -> None: logger.debug(f"message hex: {message.hex()}") self.message = message
def mock_reader__cmd(self, command: str) -> bytes: """bypass serial.write/read""" logger.debug(f"mock write/read: {command}") nonlocal data return next(data) if command == "passive_read" else b""