UIFlow2 & M5Paper
-
Hi,
I'm trying to get my m5paper up and running with a basic app to toggle a device.
The code displays temperature, humidity, co2, IAQ Level all correctly, but the touch interaction with the device is not working - any tips? Also, am I correctly implementing the sleep?
Thanks so much in advance!
D
import os, sys, io import M5 from M5 import * import requests2 import time import json # Global data variable data = {} data['grow_lamp_state'] = "Unknown" # To store current state # Configuration ha_url = "xxx" # Change this to your HA instance ha_token = "xxx" screenTitle = 'Office Environment' # Title to display wakeup_interval = 300 # 5 minutes in seconds # Button positioning button_x = 270 # Center X position of button button_y = 480 # Y position for button (adjust as needed) button_width = 200 # Width of button button_height = 60 # Height of button # Define constants for e-ink (black and white) WHITE = 0xffffff BLACK = 0x000000 def fetchHomeAssistantData(entity_id): url = f"{ha_url}/api/states/{entity_id}" headers = { 'Authorization': f'Bearer {ha_token}', 'Content-Type': 'application/json' } try: response = requests2.get(url, headers=headers) if response.status_code == 200: return json.loads(response.text) else: print(f"Error: {response.status_code}") return None except Exception as e: print(f"Error fetching data: {e}") return None def toggleGrowLamp(): url = f"{ha_url}/api/services/light/toggle" headers = { 'Authorization': f'Bearer {ha_token}', 'Content-Type': 'application/json' } payload = { "entity_id": "light.grow_lamp" } try: response = requests2.post(url, headers=headers, data=json.dumps(payload)) if response.status_code == 200: print("Toggled grow lamp successfully") # Update our stored state (will be refreshed next time) data['grow_lamp_state'] = "on" if data['grow_lamp_state'] == "off" else "off" # Force a re-render render() return True else: print(f"Error toggling grow lamp: {response.status_code}") return False except Exception as e: print(f"Error toggling grow lamp: {e}") return False def aggregateData(): global data # Device data try: data['batteryPercentage'] = str(M5.Power.getBatteryLevel()) + '%' data['voltage'] = f"{M5.Power.getBatVoltage() / 1000:.2f}V" except: data['batteryPercentage'] = "N/A" data['voltage'] = "N/A" # Check WiFi try: data['isWifiConnected'] = True # Assume connected except: data['isWifiConnected'] = True data['currentTime'] = time.localtime() # Fetch Home Assistant data try: # Temperature from Aranet4 temp_data = fetchHomeAssistantData("sensor.aranet4_2836d_temperature") if temp_data: data['ha_temperature'] = temp_data.get("state", "Unknown") data['ha_temperature_unit'] = temp_data.get("attributes", {}).get("unit_of_measurement", "°C") else: data['ha_temperature'] = "Error" data['ha_temperature_unit'] = "" # Humidity from Aranet4 humidity_data = fetchHomeAssistantData("sensor.aranet4_2836d_humidity") if humidity_data: data['ha_humidity'] = humidity_data.get("state", "Unknown") data['ha_humidity_unit'] = humidity_data.get("attributes", {}).get("unit_of_measurement", "%") else: data['ha_humidity'] = "Error" data['ha_humidity_unit'] = "" # CO2 from Aranet4 co2_data = fetchHomeAssistantData("sensor.aranet4_2836d_carbon_dioxide") if co2_data: data['ha_co2'] = co2_data.get("state", "Unknown") data['ha_co2_unit'] = co2_data.get("attributes", {}).get("unit_of_measurement", "ppm") else: data['ha_co2'] = "Error" data['ha_co2_unit'] = "" # IAQ from office sensor iaq_data = fetchHomeAssistantData("sensor.office_iaq_level") if iaq_data: data['ha_iaq'] = iaq_data.get("state", "Unknown") else: data['ha_iaq'] = "Error" # Grow lamp state lamp_data = fetchHomeAssistantData("light.grow_lamp") if lamp_data: data['grow_lamp_state'] = lamp_data.get("state", "Unknown") else: data['grow_lamp_state'] = "Unknown" except Exception as e: print(f"Error in aggregateData: {e}") def addZero(x): if int(x) < 10: return '0' + str(x) return str(x) def isButtonPressed(x, y): return (x >= button_x - button_width//2 and x <= button_x + button_width//2 and y >= button_y - button_height//2 and y <= button_y + button_height//2) def render(): # Clear screen M5.Lcd.fillScreen(WHITE) M5.Lcd.setTextColor(BLACK, WHITE) # Header M5.Lcd.setTextSize(2) M5.Lcd.setCursor(12, 10) M5.Lcd.print(screenTitle) M5.Lcd.drawLine(0, 40, 540, 40, BLACK) # Current time in header t = data['currentTime'] time_str = f"{addZero(t[3])}:{addZero(t[4])}" date_str = f"{t[0]}-{addZero(t[1])}-{addZero(t[2])}" M5.Lcd.setCursor(300, 10) M5.Lcd.print(f"{date_str}") # Main content area margin = 20 y_pos = 80 # Temperature display M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print("Temperature:") # Add indicator based on value try: temp_value = float(data['ha_temperature']) indicator = "" if temp_value > 25: indicator = "!" # High elif temp_value < 18: indicator = "!" # Low else: indicator = "" # Good except ValueError: indicator = "?" M5.Lcd.setTextSize(3) M5.Lcd.setCursor(250, y_pos) M5.Lcd.print(f"{data['ha_temperature']}{data['ha_temperature_unit']} {indicator}") y_pos += 80 # Reset text size M5.Lcd.setTextSize(2) # Humidity display M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print("Humidity:") try: humidity_value = float(data['ha_humidity']) indicator = "" if humidity_value > 60: indicator = "!" # High elif humidity_value < 40: indicator = "!" # Low else: indicator = "" # Good except ValueError: indicator = "?" M5.Lcd.setTextSize(3) M5.Lcd.setCursor(250, y_pos) M5.Lcd.print(f"{data['ha_humidity']}{data['ha_humidity_unit']} {indicator}") y_pos += 80 # Reset text size M5.Lcd.setTextSize(2) # CO2 display M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print("CO2:") try: co2_value = float(data['ha_co2']) indicator = "" if co2_value > 1000: indicator = "!" # Warning else: indicator = "" # Good except ValueError: indicator = "?" M5.Lcd.setTextSize(3) M5.Lcd.setCursor(250, y_pos) M5.Lcd.print(f"{data['ha_co2']} {data['ha_co2_unit']} {indicator}") y_pos += 80 # Reset text size M5.Lcd.setTextSize(2) # IAQ display M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print("IAQ Level:") M5.Lcd.setTextSize(3) M5.Lcd.setCursor(250, y_pos) M5.Lcd.print(f"{data['ha_iaq']}") y_pos += 100 # Reset text size M5.Lcd.setTextSize(2) # Divider line M5.Lcd.drawLine(margin, y_pos, 540-margin, y_pos, BLACK) y_pos += 40 # Grow Lamp Control Button global button_y button_y = y_pos # Set the button Y position dynamically # Draw button button_color = BLACK if data['grow_lamp_state'] == "on" else WHITE text_color = WHITE if data['grow_lamp_state'] == "on" else BLACK M5.Lcd.fillRoundRect( button_x - button_width//2, button_y - button_height//2, button_width, button_height, 10, # Corner radius button_color ) # Draw button border M5.Lcd.drawRoundRect( button_x - button_width//2, button_y - button_height//2, button_width, button_height, 10, BLACK ) # Button text M5.Lcd.setTextSize(2) M5.Lcd.setTextColor(text_color, button_color) # Calculate centered text position text = "Grow Lamp: " + ("ON" if data['grow_lamp_state'] == "on" else "OFF") # Position for centered text text_width = len(text) * 12 # Approximate width based on font size text_x = button_x - text_width//2 text_y = button_y - 10 # Adjust for vertical centering M5.Lcd.setCursor(text_x, text_y) M5.Lcd.print(text) # Reset text color M5.Lcd.setTextColor(BLACK, WHITE) y_pos += 80 # Add space below button # Divider line after button M5.Lcd.drawLine(margin, y_pos, 540-margin, y_pos, BLACK) y_pos += 40 # Device information M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print("Device Info:") y_pos += 40 # Use smaller font for device info M5.Lcd.setTextSize(1) # Battery M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print(f"Battery: {data['batteryPercentage']}") y_pos += 30 # Voltage M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print(f"Voltage: {data['voltage']}") y_pos += 30 # WiFi status wifi_status = "Connected" if data['isWifiConnected'] else "Disconnected" M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print(f"WiFi: {wifi_status}") y_pos += 30 # Update interval M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print(f"Update Interval: {int(wakeup_interval/60)} min") y_pos += 30 # Last update time t = data['currentTime'] update_time = f"{addZero(t[3])}:{addZero(t[4])}:{addZero(t[5])}" M5.Lcd.setCursor(margin, y_pos) M5.Lcd.print(f"Last Updated: {update_time}") # For e-ink displays try: M5.update() except: pass # Main execution try: # Initialize M5.begin() # Show loading message M5.Lcd.fillScreen(WHITE) M5.Lcd.setTextColor(BLACK, WHITE) M5.Lcd.setTextSize(2) M5.Lcd.setCursor(200, 240) M5.Lcd.print("Loading...") # Try to update display try: M5.update() except: pass # Fetch data and render display aggregateData() render() # Keep awake longer to allow interaction awake_time = 30 # 30 seconds instead of 10 awake_start = time.time() last_touch_time = 0 # Wait for touch events or timeout while time.time() - awake_start < awake_time: # Check for touches using native GT911 method if hasattr(M5, 'TP'): # For newer firmware with direct touch access if hasattr(M5.TP, 'getStatus') and M5.TP.getStatus(): # Get touch point x = M5.TP.getX() y = M5.TP.getY() # Only process touch if it's a new touch (debounce) current_time = time.time() if current_time - last_touch_time > 0.5: if isButtonPressed(x, y): print(f"Button pressed at {x},{y}") toggleGrowLamp() # Reset timeout counter to give more time after interaction awake_start = time.time() last_touch_time = current_time # Alternative method for M5Paper with different touch API try: if hasattr(M5, 'TP') and hasattr(M5.TP, 'touched'): touches = M5.TP.touched() if touches > 0: # Process first touch point point = M5.TP.getPoint(0) x, y = point.x, point.y # Only process touch if it's a new touch (debounce) current_time = time.time() if current_time - last_touch_time > 0.5: if isButtonPressed(x, y): print(f"Button pressed at {x},{y}") toggleGrowLamp() # Reset timeout counter to give more time after interaction awake_start = time.time() last_touch_time = current_time except: pass # Update display if needed try: M5.update() except: pass time.sleep(0.1) # Try to sleep try: M5.Power.deepSleep(wakeup_interval * 1000) except: try: import machine machine.deepsleep(wakeup_interval * 1000) except: while True: time.sleep(3600) # Just sleep in a loop if deep sleep fails except Exception as e: # Display error M5.Lcd.fillScreen(WHITE) M5.Lcd.setTextColor(BLACK, WHITE) M5.Lcd.setTextSize(2) M5.Lcd.setCursor(20, 200) M5.Lcd.print(f"Error: {str(e)}") try: M5.update() except: pass time.sleep(60)
-
Hello @daniel-edge456
in UIFlow2 v2.2.6 using touch blocks for M5Paper and then look into the Python tab I get the following code to get touch coordinates:
if (M5.Touch.getCount()) > 0: x = M5.Touch.getX() y = M5.Touch.getY()
doing the same with power blocks I get:
Power.deepSleep(1000, True)
to put M5Paper into deep sleep.
Thanks
Felix