From c58bed1a85254bc1260e20e94e2dd67d76734743 Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Sun, 4 Feb 2024 18:49:55 -0500 Subject: [PATCH 01/10] Add PMS5003 Particulate Sensor --- mqtt_io/modules/sensor/pms5003.py | 76 +++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 mqtt_io/modules/sensor/pms5003.py diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py new file mode 100644 index 00000000..6b6ae68e --- /dev/null +++ b/mqtt_io/modules/sensor/pms5003.py @@ -0,0 +1,76 @@ +""" +PMS5003 Particulate Matter Sensor +""" + +from ...exceptions import RuntimeConfigError +from ...types import CerberusSchemaType, ConfigType, SensorValueType +from typing import cast +from . import GenericSensor +import time + +REQUIREMENTS = ("plantower",) +CONFIG_SCHEMA: CerberusSchemaType = { + "serial_port": dict(type="string", required=True, empty=False), +} + + +class Sensor(GenericSensor): + """ + Implementation of Sensor class for the PMS5003 sensor. + """ + + SENSOR_SCHEMA: CerberusSchemaType = { + "type": dict( + type="string", + required=False, + empty=False, + default="pm25_std", + allowed=["pm10_cf1", "pm25_cf1","pm100_cf1","pm10_std","pm25_std","pm100_std","gr03um","gr05um","gr10um","gr25um","gr50um","gr100um"], + ) + } + + def setup_module(self) -> None: + # pylint: disable=import-outside-toplevel,import-error + import plantower + + self.serial_port = self.config["serial_port"] + self.sensor = plantower.Plantower(port=self.serial_port) + self.sensor.mode_change(plantower.PMS_PASSIVE_MODE) + self.sensor.set_to_wakeup() + time.sleep(30) #give fan time to stabilize readings + + def get_value(self, sens_conf: ConfigType) -> SensorValueType: + """ + Get the particulate data from the sensor + """ + sleep_sensor = sens_conf["interval"] >= 120 #turn sensor off if interval between readings is >= 2 minutes + if sleep_sensor: + self.sensor.set_to_wakeup() + time.sleep(30) + sens_type = sens_conf["type"] + try: + result = self.sensor.read() + except: + return None + if sleep_sensor: + self.sensor.set_to_sleep() + return cast( + int, + dict( + pm10_cf1=result.pm10_cf1, + pm25_cf1=result.pm25_cf1, + pm100_cf1=result.pm100_cf1, + pm10_std=result.pm10_std, + pm25_std=result.pm25_std, + pm100_std=result.pm100_std, + gr03um=result.gr03um, + gr05um=result.gr05um, + gr10um=result.gr10um, + gr25um=result.gr25um, + gr50um=result.gr50um, + gr100um=result.gr100um + )[sens_type], + ) + + def cleanup(self) -> None: + self.sensor.set_to_sleep() From 788b891caa5c40f3230cda859a545f322fe2f8f7 Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Sun, 4 Feb 2024 18:54:33 -0500 Subject: [PATCH 02/10] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6c9203d1..513dd212 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Hardware support is provided by specific GPIO, Sensor and Stream modules. It's e - LM75 temperature sensor (`lm75`) - MCP3008 analog to digital converter (`mcp3008`) - ADXl345 3-axis accelerometer up to ±16g (`adxl345`) + - PMS5003 particulate sensor (`pms5003`) ### Streams From 08095c37b93d5afaf5aa433c924f75b8778b041a Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Mon, 5 Feb 2024 20:39:06 -0500 Subject: [PATCH 03/10] Update pms5003.py fix some linting errors --- mqtt_io/modules/sensor/pms5003.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py index 6b6ae68e..048493d7 100644 --- a/mqtt_io/modules/sensor/pms5003.py +++ b/mqtt_io/modules/sensor/pms5003.py @@ -2,11 +2,11 @@ PMS5003 Particulate Matter Sensor """ +import time +from typing import cast from ...exceptions import RuntimeConfigError from ...types import CerberusSchemaType, ConfigType, SensorValueType -from typing import cast from . import GenericSensor -import time REQUIREMENTS = ("plantower",) CONFIG_SCHEMA: CerberusSchemaType = { @@ -25,7 +25,11 @@ class Sensor(GenericSensor): required=False, empty=False, default="pm25_std", - allowed=["pm10_cf1", "pm25_cf1","pm100_cf1","pm10_std","pm25_std","pm100_std","gr03um","gr05um","gr10um","gr25um","gr50um","gr100um"], + allowed= + ["pm10_cf1", "pm25_cf1","pm100_cf1", + "pm10_std","pm25_std","pm100_std", + "gr03um","gr05um","gr10um", + "gr25um","gr50um","gr100um"], ) } @@ -43,7 +47,8 @@ def get_value(self, sens_conf: ConfigType) -> SensorValueType: """ Get the particulate data from the sensor """ - sleep_sensor = sens_conf["interval"] >= 120 #turn sensor off if interval between readings is >= 2 minutes + #turn sensor off if interval between readings is >= 2 minutes + sleep_sensor = sens_conf["interval"] >= 120 if sleep_sensor: self.sensor.set_to_wakeup() time.sleep(30) From db799a662cf46d12291340359223ee510d36d8c7 Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Mon, 5 Feb 2024 21:14:53 -0500 Subject: [PATCH 04/10] let sensor errors bubble up --- mqtt_io/modules/sensor/pms5003.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py index 048493d7..1beddf5e 100644 --- a/mqtt_io/modules/sensor/pms5003.py +++ b/mqtt_io/modules/sensor/pms5003.py @@ -53,10 +53,7 @@ def get_value(self, sens_conf: ConfigType) -> SensorValueType: self.sensor.set_to_wakeup() time.sleep(30) sens_type = sens_conf["type"] - try: - result = self.sensor.read() - except: - return None + result = self.sensor.read() if sleep_sensor: self.sensor.set_to_sleep() return cast( From 60ca208c99cecad958e675f05063d6985d47f542 Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Mon, 5 Feb 2024 21:15:30 -0500 Subject: [PATCH 05/10] remove unused import --- mqtt_io/modules/sensor/pms5003.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py index 1beddf5e..f9043175 100644 --- a/mqtt_io/modules/sensor/pms5003.py +++ b/mqtt_io/modules/sensor/pms5003.py @@ -4,7 +4,6 @@ import time from typing import cast -from ...exceptions import RuntimeConfigError from ...types import CerberusSchemaType, ConfigType, SensorValueType from . import GenericSensor From a57b30311b403387a2013694d4cc8c7994fc78b5 Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:15:29 -0500 Subject: [PATCH 06/10] Create sht4x.py --- mqtt_io/modules/sensor/sht4x.py | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 mqtt_io/modules/sensor/sht4x.py diff --git a/mqtt_io/modules/sensor/sht4x.py b/mqtt_io/modules/sensor/sht4x.py new file mode 100644 index 00000000..640fd91b --- /dev/null +++ b/mqtt_io/modules/sensor/sht4x.py @@ -0,0 +1,57 @@ +""" +SHT4x temperature and humidity sensor +""" + +from typing import cast + +from ...types import ConfigType, SensorValueType +from . import GenericSensor +from ...exceptions import RuntimeConfigError + +REQUIREMENTS = ("adafruit-circuitpython-sht4x",) + + +class Sensor(GenericSensor): + """ + Implementation of Sensor class for sht4x. + """ + + SENSOR_SCHEMA = { + "type": dict( + type="string", + required=False, + empty=False, + default="temperature", + allowed=["temperature", "humidity"], + ) + } + + def setup_module(self) -> None: + # pylint: disable=import-outside-toplevel,import-error + import adafruit_sht4x # type: ignore + import board # type: ignore + import busio # type: ignore + + i2c = busio.I2C(board.SCL, board.SDA) + self.sensor = adafruit_sht4x.SHT4x(i2c) + + @property + def _temperature(self) -> SensorValueType: + return cast(SensorValueType, self.sensor.temperature) + + @property + def _humidity(self) -> SensorValueType: + return cast(SensorValueType, self.sensor.relative_humidity) + + def get_value(self, sens_conf: ConfigType) -> SensorValueType: + """ + Get the temperature value from the sensor + """ + if sens_conf["type"] == "temperature": + return self._temperature + if sens_conf["type"] == "humidity": + return self._humidity + raise RuntimeConfigError( + "sht4x sensor '%s' was not configured to return 'temperature' or 'humidity'" + % sens_conf["name"] + ) From c2286c23dd934d1853637184782c104bf916f359 Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:16:37 -0500 Subject: [PATCH 07/10] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 513dd212..db86a8d1 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ Hardware support is provided by specific GPIO, Sensor and Stream modules. It's e - MCP3008 analog to digital converter (`mcp3008`) - ADXl345 3-axis accelerometer up to ±16g (`adxl345`) - PMS5003 particulate sensor (`pms5003`) + - SHT40/SHT41/SHT45 temperature and humidity sensors (`sht4x`) ### Streams From b60fb176010598db250a36f50c352f7e3e23c79e Mon Sep 17 00:00:00 2001 From: John Wang <47154554+johnwang16@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:36:47 -0500 Subject: [PATCH 08/10] Update pms5003.py --- mqtt_io/modules/sensor/pms5003.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py index f9043175..c04542e7 100644 --- a/mqtt_io/modules/sensor/pms5003.py +++ b/mqtt_io/modules/sensor/pms5003.py @@ -47,7 +47,7 @@ def get_value(self, sens_conf: ConfigType) -> SensorValueType: Get the particulate data from the sensor """ #turn sensor off if interval between readings is >= 2 minutes - sleep_sensor = sens_conf["interval"] >= 120 + sleep_sensor = sens_conf["interval"] >= 120 if sleep_sensor: self.sensor.set_to_wakeup() time.sleep(30) From bf25a2bfc88a2722d9781559aa18bff835489785 Mon Sep 17 00:00:00 2001 From: Benji <46675043+BenjiU@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:00:10 +0100 Subject: [PATCH 09/10] ignore_missing_imports for plantower --- mqtt_io/modules/sensor/pms5003.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py index c04542e7..bf458ed3 100644 --- a/mqtt_io/modules/sensor/pms5003.py +++ b/mqtt_io/modules/sensor/pms5003.py @@ -33,7 +33,7 @@ class Sensor(GenericSensor): } def setup_module(self) -> None: - # pylint: disable=import-outside-toplevel,import-error + # pylint: disable=import-outside-toplevel,import-error,ignore_missing_imports import plantower self.serial_port = self.config["serial_port"] From a5936daab2f9314156b8a672b0a572d959a9053e Mon Sep 17 00:00:00 2001 From: Benji <46675043+BenjiU@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:05:29 +0100 Subject: [PATCH 10/10] ignore "Missing library stubs or py.typed marker" for plantower --- mqtt_io/modules/sensor/pms5003.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mqtt_io/modules/sensor/pms5003.py b/mqtt_io/modules/sensor/pms5003.py index bf458ed3..7a0a1157 100644 --- a/mqtt_io/modules/sensor/pms5003.py +++ b/mqtt_io/modules/sensor/pms5003.py @@ -33,8 +33,8 @@ class Sensor(GenericSensor): } def setup_module(self) -> None: - # pylint: disable=import-outside-toplevel,import-error,ignore_missing_imports - import plantower + # pylint: disable=import-outside-toplevel,import-error + import plantower # type: ignore self.serial_port = self.config["serial_port"] self.sensor = plantower.Plantower(port=self.serial_port)