mirror of
https://github.com/OMGeeky/homecontrol.esp-sensors.git
synced 2026-02-23 15:49:52 +01:00
improve display & reorder operations
also switch to umqtt.robust form umqtt.simple for basic reconnects this should change it, so it shows the values quickly after startup and only then tries to connect to wifi and mqtt for uploading, while still showing the values also has a status bar now
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ config.json
|
||||
/deploy/upload/
|
||||
/deploy/last_upload/
|
||||
/deploy/actual_upload/
|
||||
__pycache__
|
||||
|
||||
@@ -10,7 +10,7 @@ import json
|
||||
|
||||
# Import hardware-specific modules if available (for ESP32/ESP8266)
|
||||
try:
|
||||
from umqtt.simple import MQTTClient
|
||||
from umqtt.robust import MQTTClient
|
||||
|
||||
SIMULATION = False
|
||||
except ImportError:
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
"""
|
||||
OLED display module for ESP32 using SSD1306 controller.
|
||||
"""
|
||||
LINE_HEIGHT = 8 # Height of each line in pixels
|
||||
|
||||
HEADER_LINE = 0
|
||||
STATUS_LINE = 1
|
||||
VALUE_LINES_START = 2
|
||||
|
||||
try:
|
||||
from machine import Pin, I2C
|
||||
@@ -18,16 +23,16 @@ class OLEDDisplay(Sensor):
|
||||
"""SSD1306 OLED display implementation."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = None,
|
||||
scl_pin: int = None,
|
||||
sda_pin: int = None,
|
||||
width: int = None,
|
||||
height: int = None,
|
||||
address: int | str = None,
|
||||
interval: int = None,
|
||||
on_time: int = None,
|
||||
display_config = None,
|
||||
self,
|
||||
name: str = None,
|
||||
scl_pin: int = None,
|
||||
sda_pin: int = None,
|
||||
width: int = None,
|
||||
height: int = None,
|
||||
address: int | str = None,
|
||||
interval: int = None,
|
||||
on_time: int = None,
|
||||
display_config=None,
|
||||
):
|
||||
"""
|
||||
Initialize a new OLED display.
|
||||
@@ -84,7 +89,7 @@ class OLEDDisplay(Sensor):
|
||||
if not SIMULATION:
|
||||
try:
|
||||
print("Initializing OLED display...")
|
||||
print(f" SCL pin: {self.scl_pin }, SDA pin: {self.sda_pin}")
|
||||
print(f" SCL pin: {self.scl_pin}, SDA pin: {self.sda_pin}")
|
||||
# print('initializing scl pin', type(self.scl_pin), self.scl_pin)
|
||||
scl = Pin(self.scl_pin)
|
||||
# print('initializing sda pin', type(self.sda_pin), self.sda_pin)
|
||||
@@ -106,6 +111,7 @@ class OLEDDisplay(Sensor):
|
||||
print(f"Simulated OLED display initialized: {width}x{height}")
|
||||
self._display = None
|
||||
|
||||
# region basic display methods
|
||||
def clear(self):
|
||||
"""
|
||||
Clear the display.
|
||||
@@ -134,6 +140,23 @@ class OLEDDisplay(Sensor):
|
||||
self._display.text(text, x, y, color)
|
||||
self._display.show()
|
||||
|
||||
def set_line_text(self, i, value):
|
||||
if SIMULATION:
|
||||
print(f"Simulated OLED display line {i}: {value}")
|
||||
else:
|
||||
if self._display:
|
||||
y = i * LINE_HEIGHT
|
||||
if y < self.height: # Make sure we don't go off the screen
|
||||
x = 0
|
||||
self._display.fill_rect(x, y, self.width, LINE_HEIGHT, 0) # Clear the line
|
||||
self._display.text(str(value), x, y, 1)
|
||||
else:
|
||||
print(f"Line {i} exceeds display height, skipping")
|
||||
|
||||
# endregion
|
||||
|
||||
# region easy setter methods
|
||||
|
||||
def display_values(self, values: list):
|
||||
"""
|
||||
Display a list of values on the OLED screen.
|
||||
@@ -149,15 +172,38 @@ class OLEDDisplay(Sensor):
|
||||
print(f" Line {i}: {value}")
|
||||
else:
|
||||
if self._display:
|
||||
self._display.fill(0) # Clear the display
|
||||
|
||||
# self._display.fill(0) # Clear the display
|
||||
x = 0
|
||||
y = VALUE_LINES_START * LINE_HEIGHT
|
||||
self._display.fill_rect(x, y, self.width, self.height-y, 0) # Clear the line
|
||||
# Display each value on a new line (8 pixels per line)
|
||||
for i, value in enumerate(values):
|
||||
if i * 10 < self.height: # Make sure we don't go off the screen
|
||||
self._display.text(str(value), 0, i * 10, 1)
|
||||
self.set_line_text(VALUE_LINES_START + i, value)
|
||||
|
||||
self._display.show()
|
||||
|
||||
def set_header(self, value):
|
||||
"""
|
||||
Display a header on the OLED screen.
|
||||
|
||||
Args:
|
||||
value: The header to display
|
||||
"""
|
||||
self.set_line_text(HEADER_LINE, value)
|
||||
|
||||
def set_status(self, status: str):
|
||||
"""
|
||||
Display a status message on the OLED screen.
|
||||
|
||||
Args:
|
||||
status: The status message to display
|
||||
"""
|
||||
self.set_line_text(STATUS_LINE, status)
|
||||
self._display.show()
|
||||
|
||||
# endregion
|
||||
|
||||
# region Sensor interface methods
|
||||
def read(self) -> float:
|
||||
"""
|
||||
Update the display (placeholder to satisfy Sensor interface).
|
||||
@@ -185,3 +231,4 @@ class OLEDDisplay(Sensor):
|
||||
metadata["type"] = "SSD1306"
|
||||
metadata["values_count"] = len(self._values)
|
||||
return metadata
|
||||
# endregion
|
||||
|
||||
85
src/main.py
85
src/main.py
@@ -98,19 +98,13 @@ def main():
|
||||
|
||||
# Initialize an OLED display using configuration
|
||||
display = OLEDDisplay(display_config=display_config)
|
||||
display.clear()
|
||||
display.display_text("Initializing...")
|
||||
# display.clear()
|
||||
name_str = f"N: {dht_sensor.name}"
|
||||
display.set_header(name_str)
|
||||
display.set_status("Initializing...")
|
||||
|
||||
# Initialize wifi connection
|
||||
display.clear()
|
||||
display.display_text("Connecting to WiFi...")
|
||||
connect_wifi(network_config)
|
||||
|
||||
# Set up MQTT client if enabled
|
||||
display.clear()
|
||||
display.display_text("Setting up MQTT...")
|
||||
mqtt_client = setup_mqtt(mqtt_config)
|
||||
# mqtt_client = None
|
||||
mqtt_enabled = mqtt_config.get("enabled", False)
|
||||
mqtt_publish_interval = mqtt_config.get("publish_interval", 60)
|
||||
|
||||
# # Set up button using configuration
|
||||
@@ -124,50 +118,57 @@ def main():
|
||||
# Main loop - sleep until button press, then read and display sensor data
|
||||
try:
|
||||
# while True:
|
||||
print('sleeping for 5 seconds for debugging')
|
||||
display.clear()
|
||||
display.display_text('debug sleeping')
|
||||
time.sleep(5)
|
||||
# print('sleeping for 5 seconds for debugging')
|
||||
# display.set_status('debug sleeping')
|
||||
# time.sleep(5)
|
||||
|
||||
# Read sensor values
|
||||
display.clear()
|
||||
display.display_text("Reading sensor values...")
|
||||
display.set_status("Reading sensor values...")
|
||||
temperature = dht_sensor.read_temperature()
|
||||
humidity = dht_sensor.read_humidity()
|
||||
|
||||
# Publish to MQTT
|
||||
display.clear()
|
||||
display.display_values(['Publishing to MQTT...', '', mqtt_client.server, mqtt_client.port])
|
||||
publish_sensor_data(mqtt_client, mqtt_config, dht_sensor, temperature, humidity)
|
||||
if mqtt_client:
|
||||
try:
|
||||
mqtt_client.disconnect()
|
||||
print("MQTT client disconnected")
|
||||
except Exception as e:
|
||||
print(f"Error disconnecting MQTT client: {e}")
|
||||
|
||||
# # Format values for display
|
||||
name_str = f"Sensor: {dht_sensor.name}"
|
||||
temp_str = f"Temp: {temperature:.1f} C"
|
||||
hum_str = f"Humidity: {humidity:.1f}%"
|
||||
time_str = f"Time: {time.time():.0f}"
|
||||
|
||||
# Display values
|
||||
## TODO: only display values, if the button has been clicked
|
||||
display.clear()
|
||||
display.display_values(
|
||||
[name_str, '', temp_str, hum_str, time_str, "Press button again"]
|
||||
)
|
||||
time.sleep(display.on_time)
|
||||
|
||||
# Print to console
|
||||
print('='*20)
|
||||
print(f"{temp_str}, {hum_str}")
|
||||
print('='*20)
|
||||
|
||||
|
||||
# Display values
|
||||
## TODO: only display values, if the button has been clicked
|
||||
display.display_values(
|
||||
[temp_str, hum_str, time_str]
|
||||
)
|
||||
|
||||
# Publish to MQTT
|
||||
if mqtt_enabled:
|
||||
# Initialize wifi connection
|
||||
display.set_status("Connecting WiFi...")
|
||||
connect_wifi(network_config)
|
||||
|
||||
# Set up MQTT client if enabled
|
||||
display.set_status("Setting up MQTT...")
|
||||
mqtt_client = setup_mqtt(mqtt_config)
|
||||
display.set_status("Publishing to MQTT...")
|
||||
# display.display_values([mqtt_client.server, mqtt_client.port])
|
||||
publish_sensor_data(mqtt_client, mqtt_config, dht_sensor, temperature, humidity)
|
||||
try:
|
||||
if mqtt_client:
|
||||
mqtt_client.disconnect()
|
||||
print("MQTT client disconnected")
|
||||
except Exception as e:
|
||||
print(f"Error disconnecting MQTT client: {e}")
|
||||
|
||||
display.set_status("...")
|
||||
# sleep, to be able to do something, before going into deepsleep
|
||||
time.sleep(display.on_time)
|
||||
|
||||
time_until_next_read = mqtt_publish_interval - (time.time() - last_read_time)
|
||||
display.set_status(f"Sleeping {time_until_next_read}s")
|
||||
print('sleeping for', time_until_next_read, 'seconds')
|
||||
if not SIMULATION:
|
||||
deepsleep(time_until_next_read * 1000)
|
||||
@@ -176,7 +177,6 @@ def main():
|
||||
print(f"Simulated deep sleep for {time_until_next_read:.1f} seconds")
|
||||
time.sleep(time_until_next_read)
|
||||
|
||||
|
||||
except KeyboardInterrupt:
|
||||
# Clean up on exit
|
||||
display.clear()
|
||||
@@ -222,4 +222,11 @@ def connect_wifi(network_config: dict):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
time.sleep(5) # give time to read the error message and respond
|
||||
deepsleep(1) # dummy deepsleep to basically reset the system
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user