|
| 1 | +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries |
| 3 | +# |
| 4 | +# SPDX-License-Identifier: MIT |
| 5 | +import time |
| 6 | +import board |
| 7 | +import json |
| 8 | +import adafruit_dps310 |
| 9 | +import adafruit_ahtx0 |
| 10 | +from adafruit_display_shapes.circle import Circle |
| 11 | +from adafruit_funhouse import FunHouse |
| 12 | + |
| 13 | +PUBLISH_DELAY = 60 |
| 14 | +ENVIRONMENT_CHECK_DELAY = 1 |
| 15 | +ENABLE_PIR = True |
| 16 | +MQTT_TOPIC = "funhouse/state" |
| 17 | +LIGHT_STATE_TOPIC = "funhouse/light/state" |
| 18 | +LIGHT_COMMAND_TOPIC = "funhouse/light/set" |
| 19 | +INITIAL_LIGHT_COLOR = 0x008000 |
| 20 | +USE_FAHRENHEIT = True |
| 21 | + |
| 22 | +try: |
| 23 | + from secrets import secrets |
| 24 | +except ImportError: |
| 25 | + print("WiFi secrets are kept in secrets.py, please add them there!") |
| 26 | + raise |
| 27 | + |
| 28 | +# Connect to the Sensors |
| 29 | +i2c = board.I2C() |
| 30 | +dps310 = adafruit_dps310.DPS310(i2c) |
| 31 | +aht20 = adafruit_ahtx0.AHTx0(i2c) |
| 32 | + |
| 33 | +funhouse = FunHouse(default_bg=0x0F0F00) |
| 34 | +funhouse.peripherals.dotstars.fill(INITIAL_LIGHT_COLOR) |
| 35 | + |
| 36 | +funhouse.display.show(None) |
| 37 | +funhouse.add_text( |
| 38 | + text="Temperature:", |
| 39 | + text_position=(20, 30), |
| 40 | + text_color=0xFF8888, |
| 41 | + text_font="fonts/Arial-Bold-24.pcf", |
| 42 | +) |
| 43 | +temp_label = funhouse.add_text( |
| 44 | + text_position=(120, 60), |
| 45 | + text_anchor_point=(0.5, 0.5), |
| 46 | + text_color=0xFFFF00, |
| 47 | + text_font="fonts/Arial-Bold-24.pcf", |
| 48 | +) |
| 49 | +funhouse.add_text( |
| 50 | + text="Humidity:", |
| 51 | + text_position=(20, 100), |
| 52 | + text_color=0x8888FF, |
| 53 | + text_font="fonts/Arial-Bold-24.pcf", |
| 54 | +) |
| 55 | +hum_label = funhouse.add_text( |
| 56 | + text_position=(120, 130), |
| 57 | + text_anchor_point=(0.5, 0.5), |
| 58 | + text_color=0xFFFF00, |
| 59 | + text_font="fonts/Arial-Bold-24.pcf", |
| 60 | +) |
| 61 | +funhouse.add_text( |
| 62 | + text="Pressure:", |
| 63 | + text_position=(20, 170), |
| 64 | + text_color=0xFF88FF, |
| 65 | + text_font="fonts/Arial-Bold-24.pcf", |
| 66 | +) |
| 67 | +pres_label = funhouse.add_text( |
| 68 | + text_position=(120, 200), |
| 69 | + text_anchor_point=(0.5, 0.5), |
| 70 | + text_color=0xFFFF00, |
| 71 | + text_font="fonts/Arial-Bold-24.pcf", |
| 72 | +) |
| 73 | +funhouse.display.show(funhouse.splash) |
| 74 | + |
| 75 | +status = Circle(229, 10, 10, fill=0xFF0000, outline=0x880000) |
| 76 | +funhouse.splash.append(status) |
| 77 | + |
| 78 | + |
| 79 | +def update_enviro(): |
| 80 | + global environment |
| 81 | + environment["temperature"] = aht20.temperature |
| 82 | + environment["pressure"] = dps310.pressure |
| 83 | + environment["humidity"] = aht20.relative_humidity |
| 84 | + environment["light"] = funhouse.peripherals.light |
| 85 | + |
| 86 | + temp = environment["temperature"] |
| 87 | + unit = "C" |
| 88 | + if USE_FAHRENHEIT: |
| 89 | + temp = temp * (9 / 5) + 32 |
| 90 | + unit = "F" |
| 91 | + funhouse.set_text("{:.1f}{}".format(temp, unit), temp_label) |
| 92 | + funhouse.set_text("{:.1f}%".format(environment["humidity"]), hum_label) |
| 93 | + funhouse.set_text("{}kPa".format(environment["light"]), pres_label) |
| 94 | + |
| 95 | + |
| 96 | +def connected(client, userdata, result, payload): |
| 97 | + status.fill = 0x00FF00 |
| 98 | + status.outline = 0x008800 |
| 99 | + print("Connected to MQTT! Subscribing...") |
| 100 | + client.subscribe(LIGHT_COMMAND_TOPIC) |
| 101 | + |
| 102 | + |
| 103 | +def disconnected(client): |
| 104 | + status.fill = 0xFF0000 |
| 105 | + status.outline = 0x880000 |
| 106 | + |
| 107 | + |
| 108 | +def message(client, topic, payload): |
| 109 | + print("Topic {0} received new value: {1}".format(topic, payload)) |
| 110 | + if topic == LIGHT_COMMAND_TOPIC: |
| 111 | + settings = json.loads(payload) |
| 112 | + print(settings) |
| 113 | + if settings["state"] == "on": |
| 114 | + if "brightness" in settings: |
| 115 | + funhouse.peripherals.dotstars.brightness = settings["brightness"] / 255 |
| 116 | + else: |
| 117 | + funhouse.peripherals.dotstars.brightness = 0.3 |
| 118 | + if "color" in settings: |
| 119 | + funhouse.peripherals.dotstars.fill(settings["color"]) |
| 120 | + else: |
| 121 | + funhouse.peripherals.dotstars.brightness = 0 |
| 122 | + publish_light_state() |
| 123 | + |
| 124 | + |
| 125 | +def publish_light_state(): |
| 126 | + funhouse.peripherals.led = True |
| 127 | + output = { |
| 128 | + "brightness": funhouse.peripherals.dotstars.brightness * 255, |
| 129 | + "state": "on" if funhouse.peripherals.dotstars.brightness > 0 else "off", |
| 130 | + "color": funhouse.peripherals.dotstars[0], |
| 131 | + } |
| 132 | + # Publish the Dotstar State |
| 133 | + print("Publishing to {}".format(LIGHT_STATE_TOPIC)) |
| 134 | + funhouse.network.mqtt_publish(LIGHT_STATE_TOPIC, json.dumps(output)) |
| 135 | + funhouse.peripherals.led = False |
| 136 | + |
| 137 | + |
| 138 | +# Initialize a new MQTT Client object |
| 139 | +funhouse.network.init_mqtt( |
| 140 | + secrets["mqtt_broker"], |
| 141 | + secrets["mqtt_port"], |
| 142 | + secrets["mqtt_username"], |
| 143 | + secrets["mqtt_password"], |
| 144 | +) |
| 145 | +funhouse.network.on_mqtt_connect = connected |
| 146 | +funhouse.network.on_mqtt_disconnect = disconnected |
| 147 | +funhouse.network.on_mqtt_message = message |
| 148 | + |
| 149 | +print("Attempting to connect to {}".format(secrets["mqtt_broker"])) |
| 150 | +funhouse.network.mqtt_connect() |
| 151 | +last_publish_timestamp = None |
| 152 | + |
| 153 | +last_peripheral_state = { |
| 154 | + "button_up": funhouse.peripherals.button_up, |
| 155 | + "button_down": funhouse.peripherals.button_down, |
| 156 | + "button_sel": funhouse.peripherals.button_sel, |
| 157 | + "captouch6": funhouse.peripherals.captouch6, |
| 158 | + "captouch7": funhouse.peripherals.captouch7, |
| 159 | + "captouch8": funhouse.peripherals.captouch8, |
| 160 | +} |
| 161 | + |
| 162 | +if ENABLE_PIR: |
| 163 | + last_peripheral_state["pir_sensor"] = funhouse.peripherals.pir_sensor |
| 164 | + |
| 165 | +environment = {} |
| 166 | +update_enviro() |
| 167 | +last_environment_timestamp = time.monotonic() |
| 168 | + |
| 169 | +# Provide Initial light state |
| 170 | +publish_light_state() |
| 171 | + |
| 172 | +while True: |
| 173 | + if not environment or ( |
| 174 | + time.monotonic() - last_environment_timestamp > ENVIRONMENT_CHECK_DELAY |
| 175 | + ): |
| 176 | + update_enviro() |
| 177 | + last_environment_timestamp = time.monotonic() |
| 178 | + output = environment |
| 179 | + |
| 180 | + peripheral_state_changed = False |
| 181 | + for peripheral in last_peripheral_state: |
| 182 | + current_item_state = getattr(funhouse.peripherals, peripheral) |
| 183 | + output[peripheral] = "on" if current_item_state else "off" |
| 184 | + if last_peripheral_state[peripheral] != current_item_state: |
| 185 | + peripheral_state_changed = True |
| 186 | + last_peripheral_state[peripheral] = current_item_state |
| 187 | + |
| 188 | + if funhouse.peripherals.slider is not None: |
| 189 | + output["slider"] = funhouse.peripherals.slider |
| 190 | + |
| 191 | + # every PUBLISH_DELAY, write temp/hum/press |
| 192 | + if ( |
| 193 | + last_publish_timestamp is None |
| 194 | + or peripheral_state_changed |
| 195 | + or (time.monotonic() - last_publish_timestamp) > PUBLISH_DELAY |
| 196 | + ): |
| 197 | + print("Sending data to MQTT!") |
| 198 | + funhouse.peripherals.led = True |
| 199 | + print("Publishing to %s" % MQTT_TOPIC) |
| 200 | + funhouse.network.mqtt_publish(MQTT_TOPIC, json.dumps(output)) |
| 201 | + funhouse.peripherals.led = False |
| 202 | + last_publish_timestamp = time.monotonic() |
| 203 | + |
| 204 | + # Check any topics we are subscribed to |
| 205 | + funhouse.network.mqtt_loop(0.5) |
0 commit comments