mirror of
https://github.com/osmarks/random-stuff
synced 2025-02-07 22:50:10 +00:00
SCD4x metrics script
This commit is contained in:
parent
5881f58996
commit
e3e34aaadb
85
scd4x_prometheus.py
Normal file
85
scd4x_prometheus.py
Normal file
@ -0,0 +1,85 @@
|
||||
# refer to https://sensirion.com/media/documents/48C4B7FB/64C134E7/Sensirion_SCD4x_Datasheet.pdf
|
||||
|
||||
import smbus3
|
||||
import struct
|
||||
import time
|
||||
from prometheus_client import start_http_server, Gauge
|
||||
import sys
|
||||
|
||||
location = sys.argv[1]
|
||||
|
||||
def sensiron_bad_crc8(data):
|
||||
crc = 0xFF
|
||||
POLY = 0x31
|
||||
for byte in data:
|
||||
crc ^= byte
|
||||
for _ in range(8):
|
||||
if crc & 0x80:
|
||||
crc = (crc << 1) ^ POLY
|
||||
else:
|
||||
crc = (crc << 1)
|
||||
crc &= 0xFF
|
||||
return crc
|
||||
|
||||
bus = smbus3.SMBus(1)
|
||||
ADDR = 0x62
|
||||
|
||||
def encode_word_crc(hi, lo):
|
||||
return [hi, lo, sensiron_bad_crc8([hi, lo])]
|
||||
|
||||
def setup():
|
||||
stop_measurement = smbus3.i2c_msg.write(ADDR, [0x3f, 0x86])
|
||||
bus.i2c_rdwr(stop_measurement)
|
||||
time.sleep(0.5)
|
||||
|
||||
serial_cmd = smbus3.i2c_msg.write(ADDR, [0x36, 0x82]) # serial number
|
||||
serial_read = smbus3.i2c_msg.read(ADDR, 9)
|
||||
bus.i2c_rdwr(serial_cmd, serial_read)
|
||||
serial = bytes(serial_read)
|
||||
print((serial[0:2] + serial[3:5] + serial[6:8]).hex())
|
||||
time.sleep(0.1)
|
||||
# automatic self-calibration breaks badly if CO2 never below 400ppm, which is not guaranteed
|
||||
disable_asc = smbus3.i2c_msg.write(ADDR, [0x24, 0x16] + encode_word_crc(0x00, 0x00))
|
||||
bus.i2c_rdwr(disable_asc)
|
||||
time.sleep(0.1)
|
||||
|
||||
# default offset of 4 degrees C is "probably right" but I don't have the equipment to test this
|
||||
#real_offset = 4.0
|
||||
#offset_bytes = struct.pack(">H", int(real_offset * 65535.0 / 175.0))
|
||||
#set_temp_offset = smbus3.i2c_msg.write(ADDR, [0x24, 0x1d] + encode_word_crc(*offset_bytes))
|
||||
#bus.i2c_rdwr(set_temp_offset)
|
||||
#time.sleep(0.1)
|
||||
|
||||
start_measurement = smbus3.i2c_msg.write(ADDR, [0x21, 0xb1])
|
||||
bus.i2c_rdwr(start_measurement)
|
||||
|
||||
setup()
|
||||
|
||||
temperature = Gauge("scd4x_temperature", "Temperature in Celsius", ("location",))
|
||||
co2_ppm = Gauge("scd4x_co2_ppm", "CO2 parts per million", ("location",))
|
||||
rh = Gauge("scd4x_relative_humidity_percent", "Relative humidity in percent", ("location",))
|
||||
|
||||
def read_temperature_pressure():
|
||||
measurement_read_write = smbus3.i2c_msg.write(ADDR, [0xec, 0x05])
|
||||
measurement_read_read = smbus3.i2c_msg.read(ADDR, 9)
|
||||
bus.i2c_rdwr(measurement_read_write, measurement_read_read)
|
||||
measurement_read_read = bytes(measurement_read_read)
|
||||
|
||||
print(measurement_read_read)
|
||||
|
||||
co2 = struct.unpack(">H", measurement_read_read[0:2])[0]
|
||||
raw_temperature = struct.unpack(">H", measurement_read_read[3:5])[0]
|
||||
raw_humidity = struct.unpack(">H", measurement_read_read[6:8])[0]
|
||||
|
||||
temperature_celsius = -45 + 175 * (raw_temperature / 65535.0)
|
||||
relative_humidity = raw_humidity / 65535.0 * 100
|
||||
|
||||
temperature.labels(location=location).set(temperature_celsius)
|
||||
rh.labels(location=location).set(relative_humidity)
|
||||
co2_ppm.labels(location=location).set(co2)
|
||||
|
||||
start_http_server(9091)
|
||||
|
||||
while True:
|
||||
time.sleep(5)
|
||||
read_temperature_pressure()
|
Loading…
x
Reference in New Issue
Block a user