Compare commits

...

18 commits
v2.1 ... master

Author SHA1 Message Date
297605b81e Improved readability 2024-08-10 02:53:23 +02:00
5e673e0c0e Self implemented co2 again 2024-08-10 02:50:05 +02:00
3f083c0aed Simplified co2 2024-08-10 02:44:33 +02:00
d1bb240080 debugging 2024-08-10 02:42:20 +02:00
b0a5903c6e Merge branch 'master' of code.giller.dev:m.giller/matrix-clock 2024-08-10 02:40:40 +02:00
6066af50ac debuging 2024-08-10 02:40:33 +02:00
3cb59cc688 debuging 2024-08-10 02:40:29 +02:00
d3b2cc4c89 Fixed co2 reading 2024-08-10 02:39:16 +02:00
cb50f230b6 Implemented co2 library 2024-08-10 02:36:09 +02:00
e2fa06d94e Some small improvements 2024-08-10 01:51:00 +02:00
d2825a32ae Removed dead code 2024-08-10 01:41:16 +02:00
8d625264d1 Not using start.sh anymore 2024-08-10 01:28:18 +02:00
df102d8e4e Revert "Added temporary contrast to pattern endpoint"
This reverts commit 9715339c43.
2024-08-10 01:24:21 +02:00
aff797bcb5 Implemented co2 sensor and silent climate endpoint 2024-08-10 00:57:37 +02:00
9715339c43 Added temporary contrast to pattern endpoint 2024-05-06 22:01:20 +02:00
e44a78742e Fixed Uart serial stuff 2024-05-02 22:10:52 +02:00
7f4eae67f6 Added serial code for mh_z19c 2024-05-02 22:03:54 +02:00
ea73b3702c Simplified format for patterns 2024-03-03 18:57:53 +01:00
7 changed files with 90 additions and 17 deletions

View file

@ -4,4 +4,5 @@ fastapi
uvicorn uvicorn
fastapi-cors fastapi-cors
Adafruit_DHT Adafruit_DHT
requests requests
mh_z19

View file

@ -5,30 +5,34 @@ from config import climate_log_file, dht22_pin
from handler.dht22_climate import Dht22Climate from handler.dht22_climate import Dht22Climate
from handler.matrix_display import MatrixDisplay from handler.matrix_display import MatrixDisplay
from handler.mhz19_co2 import Mhz19Co2
climate_sensor = Dht22Climate(dht22_pin) climate_sensor = Dht22Climate(dht22_pin)
co2_sensor = Mhz19Co2()
matrix_display = MatrixDisplay() matrix_display = MatrixDisplay()
async def log_temperature(): async def log_climate(delay_sec: int = 60):
# If file does not exist, create it and write header # If file does not exist, create it and write header
if not os.path.isfile(climate_log_file): if not os.path.isfile(climate_log_file):
with open(climate_log_file, "w") as f: with open(climate_log_file, "w") as f:
f.write("timestamp,temperature,humidity\n") f.write("timestamp,temperature,humidity,co2\n")
while True: while True:
measurements = climate_sensor.read() measurements = climate_sensor.read()
co2_density = co2_sensor.read()
if measurements is not None: if measurements is not None:
with open(climate_log_file, "a") as f: with open(climate_log_file, "a") as f:
f.write( f.write(
"{},{},{}\n".format( "{},{},{},{}\n".format(
datetime.now().isoformat(), datetime.now().isoformat(),
measurements["temperature"], measurements["temperature"],
measurements["humidity"], measurements["humidity"],
co2_density,
) )
) )
await asyncio.sleep(60) await asyncio.sleep(delay_sec)
async def display_time(): async def display_time():

View file

@ -8,12 +8,12 @@ class Dht22Climate:
self.pin = pin self.pin = pin
self.last_read = None self.last_read = None
def get_last_read(self): def get_last_read(self) -> dict | None:
if self.last_read is None: if self.last_read is None:
return self.read() return self.read()
return self.last_read return self.last_read
def read(self): def read(self) -> dict | None:
humidity, temperature = Adafruit_DHT.read_retry(self.sensor, self.pin) humidity, temperature = Adafruit_DHT.read_retry(self.sensor, self.pin)
if humidity is not None and temperature is not None: if humidity is not None and temperature is not None:
self.last_read = {"temperature": temperature, "humidity": humidity} self.last_read = {"temperature": temperature, "humidity": humidity}

View file

@ -68,9 +68,9 @@ class MatrixDisplay:
with canvas(self.device) as draw: with canvas(self.device) as draw:
draw.rectangle((0, 0, 31, 7), outline="white", fill="white") draw.rectangle((0, 0, 31, 7), outline="white", fill="white")
async def pattern(self, pattern: str = "0,1", step_ms: int = 500): async def pattern(self, pattern: str = "01", step_ms: int = 500):
# Parse # Parse
pattern_steps = [step.strip() == "1" for step in pattern.split(",") if step] pattern_steps = [step.strip() == "1" for step in pattern]
# Execute # Execute
for step in pattern_steps: for step in pattern_steps:
if step: if step:

48
src/handler/mhz19_co2.py Normal file
View file

@ -0,0 +1,48 @@
import serial
class Mhz19Co2:
def __init__(self):
self.last_read = None
self.serial_port = "/dev/serial0"
self.baud_rate = 9600
self.byte_size = 8
self.parity = "N"
self.stop_bits = 1
self.timeout = None
def get_last_read(self) -> int | None:
if self.last_read is None:
return self.read()
return self.last_read
def read(self) -> int | None:
ser = None
try:
ser = serial.Serial(
port=self.serial_port,
baudrate=self.baud_rate,
bytesize=self.byte_size,
parity=self.parity,
stopbits=self.stop_bits,
timeout=self.timeout,
)
# send "Read CO2" command
command_data = bytes([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])
ser.write(command_data)
# read "Return Value (CO2 concentration)"
data = ser.read(9)
concentration = data[2] * 256 + data[3]
except Exception as e:
print(f"Error reading data: {e}")
finally:
if ser:
ser.close()
ser = None
self.last_read = concentration
return concentration

View file

@ -8,9 +8,9 @@ from fastapi.middleware.cors import CORSMiddleware
from actions import ( from actions import (
climate_sensor, climate_sensor,
display_time, display_time,
log_temperature,
matrix_display, matrix_display,
display_pattern, display_pattern,
co2_sensor,
) )
from config import climate_log_file from config import climate_log_file
from handler.action_queue import ActionQueue from handler.action_queue import ActionQueue
@ -20,7 +20,6 @@ logging.getLogger().setLevel(logging.INFO)
# Start services # Start services
asyncio.create_task(log_temperature())
queue = ActionQueue(matrix_display.show_current_time) queue = ActionQueue(matrix_display.show_current_time)
app = FastAPI() app = FastAPI()
@ -62,7 +61,7 @@ async def turn_off():
@app.post("/temperature") @app.post("/temperature")
async def temperature(): async def temperature():
measurements = climate_sensor.get_last_read() measurements = climate_sensor.read()
if measurements is None: if measurements is None:
return {"message": "Failed to read temperature"} return {"message": "Failed to read temperature"}
@ -75,7 +74,7 @@ async def temperature():
@app.post("/humidity") @app.post("/humidity")
async def humidity(): async def humidity():
measurements = climate_sensor.get_last_read() measurements = climate_sensor.read()
if measurements is None: if measurements is None:
return {"message": "Failed to read humidity"} return {"message": "Failed to read humidity"}
@ -86,6 +85,30 @@ async def humidity():
return measurements return measurements
@app.post("/co2")
async def co2():
co2 = co2_sensor.read()
if co2 is None:
return {"message": "Failed to read co2"}
await queue.add_action_to_queue(matrix_display.show_text, f"{co2} ppm")
return {"co2": co2}
@app.post("/climate")
async def climate():
measurements = climate_sensor.read()
if measurements is None:
return {"message": "Failed to read humidy and temperature"}
co2 = co2_sensor.read()
if co2 is None:
return {"message": "Failed to read co2"}
return {"co2": co2, **measurements}
@app.post("/history") @app.post("/history")
async def history(): async def history():
day_entry_count = 24 * 60 day_entry_count = 24 * 60
@ -101,7 +124,7 @@ async def flash(count: int = 1, contrast: Optional[int] = None):
@app.post("/pattern") @app.post("/pattern")
async def flash(pattern: str = "0,1", step_ms: int = 500): async def flash(pattern: str = "01", step_ms: int = 500):
await queue.set_idle_action(display_pattern, pattern=pattern, step_ms=step_ms) await queue.set_idle_action(display_pattern, pattern=pattern, step_ms=step_ms)
return {"message": "Activated pattern."} return {"message": "Activated pattern."}

View file

@ -1,3 +0,0 @@
cd /home/pi/matrix-clock/src
uvicorn main:app --reload --host 0.0.0.0