Use as a library
PyPMS
/pms
is meant as a command line application.
This section contain some help for those brave enough to use its internals as a library.
Basic examples
"""
Read PMSx003 sensor on /dev/ttyUSB0.
Read 4 samples, one sample every 20 seconds,
and print the observations on different formats.
"""
from pms.core import SensorReader
reader = SensorReader("PMSx003", "/dev/ttyUSB0", interval=20, samples=4)
print("\nPMSx003 4 samples on default format")
with reader:
for obs in reader():
print(obs)
print("\nPMSx003 4 samples on CSV format")
with reader:
for obs in reader():
print(f"{obs:csv}")
print("\nPMSx003 4 samples on CSV format with header")
with reader:
print_header = True
for obs in reader():
if print_header:
print(f"{obs:header}")
print_header = False
print(f"{obs:csv}")
PMSx003 4 samples on default format
2021-07-29 15:57:01: PM1 1.0, PM2.5 11.0, PM10 12.0 μg/m3
2021-07-29 15:57:21: PM1 0.0, PM2.5 6.0, PM10 6.0 μg/m3
2021-07-29 15:57:41: PM1 0.0, PM2.5 1.0, PM10 2.0 μg/m3
2021-07-29 15:58:01: PM1 0.0, PM2.5 1.0, PM10 2.0 μg/m3
PMSx003 4 samples on CSV format
1627567094, 2, 10, 12, 2.0, 10.0, 12.0, 4.35, 1.42, 0.52, 0.30, 0.00, 0.00
1627567114, 1, 7, 7, 1.0, 7.0, 7.0, 4.53, 1.44, 0.30, 0.09, 0.00, 0.00
1627567134, 1, 1, 2, 1.0, 1.0, 2.0, 3.27, 1.09, 0.09, 0.03, 0.03, 0.00
1627567154, 1, 1, 2, 1.0, 1.0, 2.0, 4.65, 1.44, 0.03, 0.00, 0.00, 0.00
PMSx003 4 samples on CSV format with header
time, raw01, raw25, raw10, pm01, pm25, pm10, n0_3, n0_5, n1_0, n2_5, n5_0, n10_0
1627567167, 2, 12, 15, 2.0, 12.0, 15.0, 5.70, 1.86, 0.68, 0.34, 0.00, 0.00
1627567187, 2, 8, 8, 2.0, 8.0, 8.0, 3.39, 1.13, 0.23, 0.09, 0.00, 0.00
1627567207, 1, 1, 1, 1.0, 1.0, 1.0, 4.26, 1.39, 0.12, 0.00, 0.00, 0.00
1627567227, 2, 2, 2, 2.0, 2.0, 2.0, 3.63, 1.21, 0.03, 0.00, 0.00, 0.00
"""
Read PMSx003 sensor on /dev/ttyUSB0
and MCU680 sensor on /dev/ttyUSB1
Read 4 samples from each sensor, one sample every 20 seconds,
and print the observations on different formats.
"""
from pms.core import SensorReader
pms = SensorReader("PMSx003", "/dev/ttyUSB0", interval=20, samples=4)
bme = SensorReader("MCU680", "/dev/ttyUSB1", interval=20, samples=4)
print("\nPMSx003 and MCU680, 4 samples each on default formats")
with pms, bme:
for pm, bm in zip(pms(), bme()):
print(pm)
print(bm)
print("\nPMSx003 and MCU680, 4 samples each on CSV format")
with pms, bme:
for pm, bm in zip(pms(), bme()):
print(f"PMSx003, {pm:csv}, MCU680, {bm:csv}")
print("\nPMSx003 and MCU680, 4 samples each on CSV format with header")
with pms, bme:
print_header = True
for pm, bm in zip(pms(), bme()):
if print_header:
print(f"PMSx003, {pm:header}, MCU680, {bm:header}")
print_header = False
print(f"PMSx003, {pm:csv}, MCU680, {bm:csv}")
PMSx003 and MCU680, 4 samples each on default formats
2021-07-29 16:01:34: PM1 1.0, PM2.5 12.0, PM10 13.0 μg/m3
2021-07-29 16:01:36: Temp. 25.1 °C, Rel.Hum. 48.3 %, Press 988.94 hPa, 463.6 kΩ
2021-07-29 16:01:54: PM1 1.0, PM2.5 5.0, PM10 5.0 μg/m3
2021-07-29 16:01:58: Temp. 25.1 °C, Rel.Hum. 48.3 %, Press 989.00 hPa, 464.9 kΩ
2021-07-29 16:02:14: PM1 0.0, PM2.5 0.0, PM10 1.0 μg/m3
2021-07-29 16:02:20: Temp. 25.1 °C, Rel.Hum. 48.2 %, Press 988.98 hPa, 467.2 kΩ
2021-07-29 16:02:34: PM1 0.0, PM2.5 0.0, PM10 1.0 μg/m3
2021-07-29 16:02:42: Temp. 25.1 °C, Rel.Hum. 48.3 %, Press 988.98 hPa, 467.5 kΩ
PMSx003 and MCU680, 4 samples each on CSV format
PMSx003, 1627567375, 1, 10, 12, 1.0, 10.0, 12.0, 4.53, 1.44, 0.56, 0.30, 0.00, 0.00, MCU680, 1627567378, 25.1, 48.2, 988.94, 257, 28, 469.8, 204
PMSx003, 1627567395, 1, 6, 7, 1.0, 6.0, 7.0, 4.86, 1.52, 0.16, 0.09, 0.00, 0.00, MCU680, 1627567400, 25.0, 48.5, 988.98, 257, 27, 470.8, 204
PMSx003, 1627567415, 2, 3, 3, 2.0, 3.0, 3.0, 2.37, 0.75, 0.03, 0.00, 0.00, 0.00, MCU680, 1627567421, 25.1, 48.2, 988.94, 257, 17, 475.8, 204
PMSx003, 1627567435, 0, 0, 0, 0.0, 0.0, 0.0, 2.97, 0.92, 0.03, 0.03, 0.00, 0.00, MCU680, 1627567443, 25.0, 48.2, 989.00, 257, 27, 474.1, 203
PMSx003 and MCU680, 4 samples each on CSV format with header
PMSx003, time, raw01, raw25, raw10, pm01, pm25, pm10, n0_3, n0_5, n1_0, n2_5, n5_0, n10_0, MCU680, time, temp, rhum, pres, IAQ_acc, IAQ, gas, alt
PMSx003, 1627567457, 1, 10, 12, 1.0, 10.0, 12.0, 4.50, 1.46, 0.60, 0.30, 0.00, 0.00, MCU680, 1627567459, 25.1, 48.2, 989.00, 257, 30, 472.8, 203
PMSx003, 1627567477, 2, 7, 7, 2.0, 7.0, 7.0, 3.87, 1.29, 0.24, 0.09, 0.00, 0.00, MCU680, 1627567481, 25.1, 48.2, 988.94, 257, 30, 474.5, 204
PMSx003, 1627567497, 1, 2, 2, 1.0, 2.0, 2.0, 3.06, 1.02, 0.10, 0.00, 0.00, 0.00, MCU680, 1627567503, 25.1, 48.1, 989.00, 258, 34, 473.1, 203
PMSx003, 1627567517, 0, 0, 0, 0.0, 0.0, 0.0, 2.16, 0.72, 0.00, 0.00, 0.00, 0.00, MCU680, 1627567525, 25.1, 47.9, 988.96, 259, 50, 467.8, 204
Observation data fields
Each sensor provides different data fields. The pms -m SENSOR_MODEL info
command will provide information about data fields and their units.
The following table shows all possible data fields and the type provided by each sensor:
--sensor-model |
pm01 | pm25 | pms04 | pm10 | pm100 | raw01 | raw25 | raw10 |
---|---|---|---|---|---|---|---|---|
PMS3003 | int | int | int | int | int | int | ||
PMSx003 | int | int | int | int | int | int | ||
PMS5003S | int | int | int | int | int | int | ||
PMS5003ST | int | int | int | int | int | int | ||
PMS5003T | int | int | int | int | int | int | ||
SDS01x | float | float | ||||||
SDS198 | int | |||||||
HPMA115S0 | int | int | ||||||
HPMA115C0 | int | int | int | int | ||||
SPS30 | float | float | float | float | ||||
ZH0xx | int | int | int | |||||
MHZ19B | ||||||||
MCU680 |
--sensor-model |
n0_3 | n0_5 | n1_0 | n2_5 | n4_0 | n5_0 | n10_0 |
---|---|---|---|---|---|---|---|
PMS3003 | float | float | float | float | float | float | |
PMSx003 | float | float | float | float | float | float | |
PMS5003S | float | float | float | float | float | float | |
PMS5003ST | float | float | float | float | float | float | |
PMS5003T | float | float | float | float | |||
SDS01x | |||||||
SDS198 | |||||||
HPMA115S0 | |||||||
HPMA115C0 | |||||||
SPS30 | float | float | float | float | float | ||
ZH0xx | |||||||
MHZ19B | |||||||
MCU680 |
On the previous example, obs
is a dataclasses.dataclass instance which an be inspected as follows
"""Inspect sensor data fields"""
from dataclasses import fields
from typing import Dict
from pms.core import Sensor
from pms.core.types import ObsData
def field_types(obs: ObsData) -> Dict[str, str]:
"""return a dictionary containing the type of each data field"""
return {field.name: field.type.__name__ for field in fields(obs)}
for sensor in Sensor:
print(sensor)
print(field_types(sensor.Data))
HPMA115C0
{'time': 'int', 'pm01': 'int', 'pm25': 'int', 'pm04': 'int', 'pm10': 'int'}
HPMA115S0
{'time': 'int', 'pm25': 'int', 'pm10': 'int'}
MCU680
{'time': 'int', 'temp': 'float', 'rhum': 'float', 'pres': 'float', 'IAQ_acc': 'int', 'IAQ': 'int', 'gas': 'int', 'alt': 'int'}
MHZ19B
{'time': 'int', 'CO2': 'int'}
PMS3003
{'time': 'int', 'raw01': 'int', 'raw25': 'int', 'raw10': 'int', 'pm01': 'int', 'pm25': 'int', 'pm10': 'int'}
PMS5003S
{'time': 'int', 'raw01': 'int', 'raw25': 'int', 'raw10': 'int', 'pm01': 'int', 'pm25': 'int', 'pm10': 'int', 'n0_3': 'float', 'n0_5': 'float', 'n1_0': 'float', 'n2_5': 'float', 'n5_0': 'float', 'n10_0': 'float', 'HCHO': 'float'}
PMS5003ST
{'time': 'int', 'raw01': 'int', 'raw25': 'int', 'raw10': 'int', 'pm01': 'int', 'pm25': 'int', 'pm10': 'int', 'n0_3': 'float', 'n0_5': 'float', 'n1_0': 'float', 'n2_5': 'float', 'n5_0': 'float', 'n10_0': 'float', 'HCHO': 'float', 'temp': 'float', 'rhum': 'float'}
PMS5003T
{'time': 'int', 'raw01': 'int', 'raw25': 'int', 'raw10': 'int', 'pm01': 'int', 'pm25': 'int', 'pm10': 'int', 'n0_3': 'float', 'n0_5': 'float', 'n1_0': 'float', 'n2_5': 'float', 'temp': 'float', 'rhum': 'float'}
PMSx003
{'time': 'int', 'raw01': 'int', 'raw25': 'int', 'raw10': 'int', 'pm01': 'int', 'pm25': 'int', 'pm10': 'int', 'n0_3': 'float', 'n0_5': 'float', 'n1_0': 'float', 'n2_5': 'float', 'n5_0': 'float', 'n10_0': 'float'}
SDS01x
{'time': 'int', 'pm25': 'float', 'pm10': 'float'}
SDS198
{'time': 'int', 'pm100': 'int'}
SPS30
{'time': 'int', 'pm01': 'float', 'pm25': 'float', 'pm04': 'float', 'pm10': 'float', 'n0_5': 'float', 'n1_0': 'float', 'n2_5': 'float', 'n4_0': 'float', 'n10_0': 'float', 'diam': 'float'}
ZH0xx
{'time': 'int', 'pm25': 'int', 'pm10': 'int', 'pm01': 'int'}
Observation formats
As the example at the top of the page shows, the obs
object has custom formats.
Observations from different sensors support different formats.
The following table shows all different formats
--sensor-model |
csv | header | pm | num | raw | cf | atm | hcho | co2 | bme | bsec |
---|---|---|---|---|---|---|---|---|---|---|---|
PMS3003 | |||||||||||
PMSx003 | |||||||||||
PMS5003T | |||||||||||
PMS5003S | |||||||||||
PMS5003ST | |||||||||||
SDS01x | |||||||||||
SDS198 | |||||||||||
HPMA115S0 | |||||||||||
HPMA115C0 | |||||||||||
SPS30 | |||||||||||
ZH0xx | |||||||||||
MHZ19B | |||||||||||
MCU680 |