🤖Have you ever tried Chat.M5Stack.com before asking??😎
    M5Stack Community
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    UIFlow2 & M5Paper

    Scheduled Pinned Locked Moved SOFTWARE
    2 Posts 2 Posters 2.0k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D Offline
      daniel.edge456
      last edited by

      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)
      
      
      
      felmueF 1 Reply Last reply Reply Quote 0
      • felmueF Offline
        felmue @daniel.edge456
        last edited by

        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

        GPIO translation table M5Stack / M5Core2
        Information about various M5Stack products.
        Code examples

        1 Reply Last reply Reply Quote 0

        Hello! It looks like you're interested in this conversation, but you don't have an account yet.

        Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

        With your input, this post could be even better 💗

        Register Login
        • First post
          Last post