avaldebe / pypms Goto Github PK
View Code? Open in Web Editor NEWData acquisition and logging for Air Quality Sensors with UART interface
Home Page: https://avaldebe.github.io/PyPMS/
License: MIT License
Data acquisition and logging for Air Quality Sensors with UART interface
Home Page: https://avaldebe.github.io/PyPMS/
License: MIT License
Trying to use pypms on my rpi zero 2w
Installed using most recent version of pip.
The pms --help
and pms serial
commands do not work - they give the error bash: pms: command not found
I am not sure what I am missing - tried the commands as root and still do not work.
I am unfamiliar with python and raspberry pi in general so any help is appreciated, I am hoping to be able to read PM measurements from my Sensiron SPS30.
From #1
- Allow readings on demand, returning readings in an appropriate structure, so that the timing and storing of data can be managed by the python app using PyPMS?
A more general use case would be to stop the data acquisition after a number successful observations. Two new options will be introduced:
The setup to capture raw data needed for #2 is a bit too involved for casual users.
For example, to capture SPS30 messages (47 bytes long) from /dev/ttyUSB0
one needs to
stty -F /dev/ttyUSB0 min 0 -icanon
tail -f /dev/ttyUSB0 | xxd -g1 -c47
The obscurity of the commands involved is not going to help gaining contributions for #2.
Besides the commands are slightly different for different sensors.
With the introduction of -n N, --samples N
on #4, one can further extend the application to provide the raw data on the right format. The following would capture 10 messages, with a frequency of 15 seconds:
pms -s /dev/ttyUSB0 -m SPS30 -n 10 -i 15 raw
Saving raw data to a file could be a good way to create sample data for testing.
This would provide a path to test the command line interface without real hardware attached.
pms -s /dev/ttyUSB0 -m SPS30 -n 10 -i 15 raw --capture
would write the raw data into a file with a well defined name pattern, e.g. start-time.pms
. In the previous example, the file name would be something line 2020-01-01_15:22:23.pms
Once we can capture raw data, caould decode it as
pms -s 2020-01-01_15:22:23.pms -m SPS30 -n 10 -i 15 raw --decode
The extension .pms
would indicate that we are not reading from a serial port.
The start time is retrieved from the filename. The complete file would be decode if number of samples (-n
) is not specified.
pms serial
and pms csv
have some overlap with pms raw-data
. Maybe this 3 sub-commands can be rolled into one.
In addition to reducing the number of options, combining this sub-commands would help with the coverage on travis builds.
the data pressure field is called pres
, not press
__post_init__
should update pres
, but instead it creates an attribute press
__format__
uses press
instead of pres
, which hides the error
PyPMS/src/pms/sensor/bosch_sensortec/mcu680.py
Lines 113 to 120 in 28644fc
Hei,
Using latest version of pms on ubuntu, I cannot make the mqtt connection to mosquitto 1.4.15 work:
pms -m SPS30 -n 1 -i 10 -s /dev/ttyUSB1 mqtt --mqtt-host localhost -t "test" throws no error, but I cannot subscribe to the feed.
mosquitto log indicates socket error:
1670442753: New client connected from 192.168.50.100 as test (c1, k60).
1670442769: Socket error on client test, disconnecting.
I have used pms serial and influx successfully for a long time, but for mqtt I could not get pms to work.
pms installed with pip: python3 -m pip install pypms[mqtt,influxdb]
As per your help in #1 , it would be helpful for others doing something similar to have instructions on how to integrate this package with their own script or application.
The tests for python3.6 and 3.7 started failing at the install stage. Tests for python3.8 are passing fine.
Local tests work file for all python versions. I suspect something wrong with the travis config.
Asked on the forum for help...
So that it can be more easily discovered and then installed with PIP
For n
attributes, the numbers are consistent, with _
representing the decimal.
For consistently and to make the numbers easier to understand, should the following change?
From | To |
---|---|
raw01 | raw1 |
raw25 | raw2_5 |
pm01 | pm1 |
pm25 | pm2_5 |
pm04 | pm4 |
Just found out a English datasheet for the PMS5003ST
, which says that the temperature is a signed integer. This total sense as the temperature can be negative.
Alas, the _unpack
unpack method inhereted from PMS3003
decodes the message as unsigned integers.
PyPMS/pms/sensor/pm/PMS3003.py
Lines 61 to 63 in 5b7d05f
Therefore, negative temperatures will show as huge values.
Hello.
I try to use your program with a PMS5003T sensor. Unfortunately not recognized. Can you help me what should be the problem?
pms -m PMS5003T -s /dev/ttyAMA0 --debug info
DEBUG:pms:capture ? PMS5003T obs from /dev/ttyAMA0 every 60 secs
Plantower PMS5003T sensor observations
time measurement time [seconds since epoch]
raw01, raw25, raw10 cf=1 PM estimates [μg/m3]
pm01, pm25, pm10 PM1.0, PM2.5, PM10 [μg/m3]
n0_3, n0_5, n1_0, n2_5 number concentrations over X.Y um [#/cm3]
temp temperature [°C]
rhum relative humidity [%]
String formats: pm (default), raw, cf, num, atm, csv and header
pms -m PMS5003T -s /dev/ttyAMA0 --debug serial
DEBUG:pms:capture ? PMS5003T obs from /dev/ttyAMA0 every 60 secs
DEBUG:pms:open /dev/ttyAMA0
DEBUG:pms:wake PMS5003T
DEBUG:pms:buffer length: 47
DEBUG:pms:message hex: 1c000b00110011000b001100110742004d001c000a00100010000a0010001007bc024a0076000800d700e39a0004e0
ERROR:pms:Sensor is not PMS5003T
The sensor itself working, because I testing it with this:
https://github.com/pjq/rpi
./monitor.sh
start monitor pm2.5...
loop times 0
http://127.0.0.1:8080/api/weather
{"lat": 0, "date": "Mon Feb 1 13:44:06 2021", "alt": 0, "temperature": 21.8, "pm10": 16, "raw_data": "", "humidity": 22.9, "pm25_cf": 16, "location": "home", "pm10_cf": 16, "pm25": 16}
Thanks
When running the pms
command, it seems to have trouble reliably identifying my SPS30 sensor. I can run it back to back a few times until the sensor is identified correctly and gives me readings. Here is example where it failed twice and worked the third time:
root@raspberrypi:/home/pi# pms -m SPS30 -n 3 -i 3 -s /dev/ttyAMA0 --debug serial -f csv
DEBUG:pms:capture 3 SPS30 obs from /dev/ttyAMA0 every 3 secs
DEBUG:pms:open /dev/ttyAMA0
DEBUG:pms:wake SPS30
DEBUG:pms:buffer length: 55
DEBUG:pms:message hex: 7e00004300bc7e7e0003002841204c59413a57fe4147f7e9414ab18542862e7d5e429d0205429fc71f42a04c1642a064f03f2b2c584c7e
DEBUG:pms:message hex: 7e0003002841204c59413a57fe4147f7e9414ab18542862e7d5e429d0205429fc71f42a04c1642a064f03f2b2c584c
ERROR:pms:Sensor is not SPS30
root@raspberrypi:/home/pi# pms -m SPS30 -n 3 -i 3 -s /dev/ttyAMA0 --debug serial -f csv
DEBUG:pms:capture 3 SPS30 obs from /dev/ttyAMA0 every 3 secs
DEBUG:pms:open /dev/ttyAMA0
DEBUG:pms:wake SPS30
DEBUG:pms:buffer length: 55
DEBUG:pms:message hex: 7e00004300bc7e7e000300284122a280413d479c414b47ec414e14c742887d3103429f438842a21ae142a2a35b42a2bcc83f2714e3b57e
DEBUG:pms:message hex: 7e000300284122a280413d479c414b47ec414e14c742887d3103429f438842a21ae142a2a35b42a2bcc83f2714e3b5
ERROR:pms:Sensor is not SPS30
root@raspberrypi:/home/pi# pms -m SPS30 -n 3 -i 3 -s /dev/ttyAMA0 --debug serial -f csv
DEBUG:pms:capture 3 SPS30 obs from /dev/ttyAMA0 every 3 secs
DEBUG:pms:open /dev/ttyAMA0
DEBUG:pms:wake SPS30
DEBUG:pms:buffer length: 54
DEBUG:pms:message hex: 7e00004300bc7e7e0003002841243d73413ef673414cf3b7414fbff94289782742a0dd0242a3b4df42a43d5d42a456dc3f23c6b63f7e
DEBUG:pms:message hex: 7e0003002841243d73413ef673414cf3b7414fbff94289782742a0dd0242a3b4df42a43d5d42a456dc3f23c6b63f7e
DEBUG:pms:message payload: (10.265002250671387, 11.935168266296387, 12.809500694274902, 12.984368324279785, 68.73467254638672, 80.43165588378906, 81.85326385498047, 82.1198501586914, 82.16964721679688, 0.6397508382797241)
DEBUG:pms:message hex: 7e00030000fc7e
DEBUG:pms:message header: b'~\x00\x03\x00\x00'
DEBUG:pms:message hex: 7e00030028411d271d41368ea94143cf3f414675c0428397334299f243429ca4c7429d2635429d3e703f26a0730f7e
DEBUG:pms:message payload: (9.822049140930176, 11.409829139709473, 12.238097190856934, 12.40374755859375, 65.7953109741211, 76.9731674194336, 78.32183074951172, 78.57462310791016, 78.6219482421875, 0.6508857607841492)
time, pm01, pm25, pm04, pm10, n0_5, n1_0, n2_5, n4_0, n10_0, diam
1630355654, 9.8, 11.4, 12.2, 12.4, 65.80, 76.97, 78.32, 78.57, 78.62, 0.7
DEBUG:pms:message hex: 7e00030028411a411e4132fe45413fd7694142693442813a33429722e84299c197429a3f3b429a56d23f26ef40507e
DEBUG:pms:message payload: (9.640897750854492, 11.187077522277832, 11.990090370178223, 12.150684356689453, 64.6136703491211, 75.56817626953125, 76.87810516357422, 77.12349700927734, 77.16957092285156, 0.6520881652832031)
1630355657, 9.6, 11.2, 12.0, 12.2, 64.61, 75.57, 76.88, 77.12, 77.17, 0.7
DEBUG:pms:message hex: 7e00030028411ab0ca41334971413fffe441428ac64281a95542979869429a3159429aadd5429ac5463f27ae40017e
DEBUG:pms:message payload: (9.668161392211914, 11.205430030822754, 11.99997329711914, 12.158880233764648, 64.83072662353516, 75.79767608642578, 77.09638214111328, 77.33951568603516, 77.38529968261719, 0.6550025939941406)
1630355660, 9.7, 11.2, 12.0, 12.2, 64.83, 75.80, 77.10, 77.34, 77.39, 0.7
DEBUG:pms:sleep SPS30
DEBUG:pms:close /dev/ttyAMA0
Here is another time it errored where the initial response from the sensor was much shorter:
root@raspberry:/home/pi# pms -m SPS30 -n 3 -i 3 -s /dev/ttyAMA0 --debug serial -f csv
DEBUG:pms:capture 3 SPS30 obs from /dev/ttyAMA0 every 3 secs
DEBUG:pms:open /dev/ttyAMA0
DEBUG:pms:wake SPS30
DEBUG:pms:buffer length: 14
DEBUG:pms:message hex: 7e00000000ff7e7e00030000fc7e
ERROR:pms:Sensor is not SPS30
I should be able to work around this by capturing the error and looping the command until I get some kind of expected results, but maybe the SPS30 has been updated and has some new identifiers? I do see the buffer length was 54 when it worked vs the 55 and 14 seen previously. No idea what might be going on.
Hardware: Raspberry Pi model B rev 2
OS: Raspbian GNU/Linux 10 (buster)
SPS30: attached to UART interface on pi (serial RX/TX, pins 8 and 10) and +5v and ground
The recently added sensor documentation contains raw output samples from all the sensors in my collection. However, as many of the supported sensors were implemented from the information available on the datasheets, the samples of the sensor output are missing.
Missing output samples, and any corrections to the documentation, are welcomed as a comment on this issue or as a PR.
A few lines of platformio device monitor -f hexlify
would suffice, or even better xxd
output as follows:
xxd -g1 -c24
xxd -g1 -c32
xxd -g1 -c32
xxd -g1 -c32
xxd -g1 -c40
xxd -g1 -c10
xxd -g1 -c10
xxd -g1 -c8
xxd -g1 -c16
xxd -g1 -c47
xxd -g1 -c20
Plantower sensors have a quirk
On my tests I found out that it is not enough to wait some time before reading from a sensor who just woke up. The sensor needs to be "exercised" a few times before the measurements become meaningful.
After a sleep/wake up cycle, the sensor the first few readings have non zero PM values but all the number concentrations are zero. IMO, this observations should be discarded so I'm considering to add an--strict
option for this. I have not observed the problem when the modules are just powered up.
Originally posted by @avaldebe in #1 (comment)
This quirk is not present after power cycling and on most cases the first observations after wake up can be discarded on post processing. However, if the sensors are read on "one-shot" mode as requested on #1, these kind of inconsistent observations need to be discarded.
The new option --strict
will take care of this kind of inconsistent observations.
Great codebase - really helpful to have all this knowledge in one place!
I've started using pms
as a library in my own project. A small problem I encountered is this line, which means I have to use force=True
when I call logging.basicConfig
in order for it to pick up my preferred settings.
Would it be possible to move that line to the pms.cli
module? I reckon that should preserve the existing behaviour for CLI users. Happy to make a PR for it but thought it would be best to ask first.
It'd be helpful to have a list of all possible attributes a reading could have, so that I can ensure I have a database column for each one and can fully support all sensors in this package, particularly as the scope now includes a variety of sensor types. I couldn't find this in a single file anywhere, so might fit best in the readme.
Dear Alvaro,
I tried to connect a Nova SDS198 to my Rpi but it does not work. I also testet a Nova SDS011 and it works just fine!
Can you help me to bug fix?
Here is the dump from the debug mode:
pi@raspberrypi:~/Desktop/PyPMS $ /home/pi/.local/bin/pms -m SDS198 -s /dev/ttyUSB0 -i 10 --debug serial
DEBUG:pms:buffer length: 20
DEBUG:pms:Guess SDS198 from buffer contents
DEBUG:pms:message hex: aacf00000000e905eeab
DEBUG:pms:message header: b'\xaa\xcf'
DEBUG:pms:message hex: aacf00000000e905eeab
DEBUG:pms:message header: b'\xaa\xcf'
DEBUG:pms:message hex: aacf00000000e905eeab
DEBUG:pms:message header: b'\xaa\xcf'
DEBUG:pms:message hex: aacf00000000e905eeab
DEBUG:pms:message header: b'\xaa\xcf'
DEBUG:pms:message hex: aacf00000000e905eeab
DEBUG:pms:message header: b'\xaa\xcf'
Cheers, Alex
Hi,
There are some issues while trying to connect to this PM sensor:
commands = hpma115s0.commands._replace(
passive_read=base.Cmd( # Read Particle Measuring Results
b"\x68\x01\x04\x93", b"\x40\x0d\x04", 16
)
)
The length of the packet is 16 bytes, hence the second byte of the response should be 0x0D ... The datasheet seems to be wrong...
Also, when receiving the ack from passive mode command it fails (wrong header length - it receives 0xA5 0xA5) - it is validated as a message (in s0 _validate)...
diff --git a/src/pms/sensors/honeywell/hpma115c0.py b/src/pms/sensors/honeywell/hpma115c0.py
index b662658..4bcc6bb 100644
--- a/src/pms/sensors/honeywell/hpma115c0.py
+++ b/src/pms/sensors/honeywell/hpma115c0.py
@@ -11,7 +11,7 @@ from . import hpma115s0
commands = hpma115s0.commands._replace(
passive_read=base.Cmd( # Read Particle Measuring Results
- b"\x68\x01\x04\x93", b"\x40\x05\x04", 16
+ b"\x68\x01\x04\x93", b"\x40\x0d\x04", 16
)
)
@@ -21,6 +21,10 @@ class Message(hpma115s0.Message):
data_records = slice(4)
+ @classmethod
+ def _validate(cls, message: bytes, header: bytes, length: int) -> base.Message:
+ return cls(message)
+
@dataclass(frozen=False)
class ObsData(base.ObsData):
It is not a fix, but at least I was able to take a sample
$ pms -s /dev/ttyUSB0 -m HPMA115C0 -n 10 -i 15 serial -f hexdump
00000000: 40 0d 04 00 04 00 07 00 09 00 17 00 00 00 00 84 @...............
00000010: 40 0d 04 00 03 00 04 00 04 00 04 00 00 00 00 a0 @...............
00000020: 40 0d 04 00 04 00 06 00 06 00 07 00 00 00 00 98 @...............
00000030: 40 0d 04 00 05 00 06 00 06 00 07 00 00 00 00 97 @...............
00000040: 40 0d 04 00 04 00 05 00 05 00 05 00 00 00 00 9c @...............
00000050: 40 0d 04 00 05 00 06 00 06 00 08 00 00 00 00 96 @...............
00000060: 40 0d 04 00 05 00 07 00 07 00 08 00 00 00 00 94 @...............
00000070: 40 0d 04 00 05 00 07 00 07 00 08 00 00 00 00 94 @...............
00000080: 40 0d 04 00 04 00 06 00 06 00 07 00 00 00 00 98 @...............
00000090: 40 0d 04 00 04 00 06 00 07 00 08 00 00 00 00 96 @...............
Hello.
Can you tell me, how can I setup the mqtt, because there is nothing about it in the readme? I would like to send the information to my local broker, but I have no idea how can I tell to pms what is the mqtt broker address, port, topic (the user and password is clear, because it can set as variable). On the other site I want to use Domoticz to log the details...
Thanks
Hello.
I trying to install this module on my raspberry pi Debian 9.11, Python 3.5.3, but it is not found :( .
Collecting pypms
Could not find a version that satisfies the requirement pypms (from versions: )
No matching distribution found for pypms
Can you help me how can i install and use it in this system?
Thanks
doc strings and output formats say HCHO [ug/m3]
where it should be [mg/m3]
My pms instance seems to break after wake up SDS198
My sensor works fine as I am able to run it continuously on my laptop but on my RPi zero W it seems to crash when running the command: "pms -m SDS198 -s /dev/serial0 -i 2 -n 10 --debug serial"
pi@raspberrypi:~ $ pms -m SDS198 -s /dev/serial0 -i 2 -n 10 --debug serial
2023-07-06 15:46:23.447 | DEBUG | pms.core.reader:__init__:109 - capture 10 SDS198 obs from /dev/serial0 every 2 secs
2023-07-06 15:46:23.464 | DEBUG | pms.core.reader:open:143 - open /dev/serial0
2023-07-06 15:46:23.470 | DEBUG | pms.core.reader:open:148 - wake SDS198
Is this a known bug? I am able to get a reading sometimes but when I want to try a second time, it breaks....
Hi
Are you planning to add functionality to:
Would be very handy having a single package that supports so many sensors!
Also, do you make use of the SET and RESET pins on the PMSA003?
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.