class Network(NetworkBase): """Class representing the Adafruit FunHouse. :param status_dotstar: The initialized object for status DotStar. Defaults to ``None``, to not use the status LED :param bool extract_values: If true, single-length fetched values are automatically extracted from lists and tuples. Defaults to ``True``. :param debug: Turn on debug print outs. Defaults to False. """ # pylint: disable=too-many-instance-attributes, too-many-locals, too-many-branches, too-many-statements def __init__( self, *, status_dotstar=None, extract_values=True, debug=False, ): super().__init__( WiFi(status_dotstar=status_dotstar), extract_values=extract_values, debug=debug, ) self._mqtt_client = None def init_io_mqtt(self): """Initialize MQTT for Adafruit IO""" try: aio_username = self._secrets["aio_username"] aio_key = self._secrets["aio_key"] except KeyError: raise KeyError( "Adafruit IO secrets are kept in secrets.py, please add them there!\n\n" ) from KeyError return self.init_mqtt(IO_MQTT_BROKER, 8883, aio_username, aio_key, True) # pylint: disable=too-many-arguments def init_mqtt( self, broker, port=8883, username=None, password=None, use_io=False, ): """Initialize MQTT""" self.connect() self._mqtt_client = MQTT.MQTT( broker=broker, port=port, username=username, password=password, socket_pool=self._wifi.pool, ssl_context=ssl.create_default_context(), ) if use_io: self._mqtt_client = IO_MQTT(self._mqtt_client) return self._mqtt_client # pylint: enable=too-many-arguments def _get_mqtt_client(self): print(self._mqtt_client) if self._mqtt_client is not None: return self._mqtt_client raise RuntimeError("Please initialize MQTT before using") def mqtt_loop(self, *args, suppress_mqtt_errors=True, **kwargs): """Run the MQTT Loop""" self._get_mqtt_client() if suppress_mqtt_errors: try: if self._mqtt_client is not None: self._mqtt_client.loop(*args, **kwargs) except MQTT.MMQTTException as err: print("MMQTTException: {0}".format(err)) except OSError as err: print("OSError: {0}".format(err)) else: if self._mqtt_client is not None: self._mqtt_client.loop(*args, **kwargs) def mqtt_publish(self, *args, suppress_mqtt_errors=True, **kwargs): """Publish to MQTT""" self._get_mqtt_client() if suppress_mqtt_errors: try: if self._mqtt_client is not None: self._mqtt_client.publish(*args, **kwargs) except OSError as err: print("OSError: {0}".format(err)) else: if self._mqtt_client is not None: self._mqtt_client.publish(*args, **kwargs) def mqtt_connect(self, *args, **kwargs): """Connect to MQTT""" self._get_mqtt_client() if self._mqtt_client is not None: self._mqtt_client.connect(*args, **kwargs) @property def on_mqtt_connect(self): """ Get or Set the MQTT Connect Handler """ if self._mqtt_client: return self._mqtt_client.on_connect return None @on_mqtt_connect.setter def on_mqtt_connect(self, value): self._get_mqtt_client() self._mqtt_client.on_connect = value @property def on_mqtt_disconnect(self): """ Get or Set the MQTT Disconnect Handler """ if self._mqtt_client: return self._mqtt_client.on_disconnect return None @on_mqtt_disconnect.setter def on_mqtt_disconnect(self, value): self._get_mqtt_client().on_disconnect = value @property def on_mqtt_subscribe(self): """ Get or Set the MQTT Subscribe Handler """ if self._mqtt_client: return self._mqtt_client.on_subscribe return None @on_mqtt_subscribe.setter def on_mqtt_subscribe(self, value): self._get_mqtt_client().on_subscribe = value @property def on_mqtt_unsubscribe(self): """ Get or Set the MQTT Unsubscribe Handler """ if self._mqtt_client: return self._mqtt_client.on_unsubscribe return None @on_mqtt_unsubscribe.setter def on_mqtt_unsubscribe(self, value): self._get_mqtt_client().on_unsubscribe = value @property def on_mqtt_message(self): """ Get or Set the MQTT Message Handler """ if self._mqtt_client: return self._mqtt_client.on_message return None @on_mqtt_message.setter def on_mqtt_message(self, value): self._get_mqtt_client().on_message = value @property def enabled(self): """ Return whether the WiFi is enabled """ return self._wifi.enabled
# Initialize a new MQTT Client object mqtt_client = MQTT.MQTT( broker="io.adafruit.com", username=secrets["aio_username"], password=secrets["aio_key"], ) # Initialize an Adafruit IO MQTT Client io = IO_MQTT(mqtt_client) # Connect the callback methods defined above to Adafruit IO io.on_connect = connected io.on_disconnect = disconnected io.on_message = message # Connect to Adafruit IO io.connect() # Start a blocking message loop... # NOTE: NO code below this loop will execute # NOTE: Network reconnection is handled within this loop while True: try: io.loop() except (ValueError, RuntimeError) as e: print("Failed to get data, retrying\n", e) wifi.reset() io.reconnect() continue time.sleep(1)
class DataWarehouse(): SECRETS_REQUIRED = ("ssid", "password", "aio_username", "aio_key") def __init__( self, secrets_, *, esp01_pins=[], esp01_uart=None, esp01_baud=115200, pub_prefix="", debug=False ### pylint: disable=redefined-outer-name ): if esp01_uart: self.esp01_uart = esp01_uart else: self.esp01_uart = busio.UART(*esp01_pins, receiver_buffer_size=2048) self.debug = debug self.esp = adafruit_espatcontrol.ESP_ATcontrol(self.esp01_uart, esp01_baud, debug=debug) self.esp_version = "" self.wifi = None try: _ = [secrets_[key] for key in self.SECRETS_REQUIRED] except KeyError: raise RuntimeError("secrets.py must contain: " + " ".join(self.SECRETS_REQUIRED)) self.secrets = secrets_ self.io = None self.pub_prefix = pub_prefix self.pub_name = {} self.init_connect() def init_connect(self): self.esp.soft_reset() self.wifi = adafruit_espatcontrol_wifimanager.ESPAT_WiFiManager( self.esp, self.secrets) ### A few retries here seems to greatly improve reliability for _ in range(4): if self.debug: print("Connecting to WiFi...") try: self.wifi.connect() self.esp_version = self.esp.get_version() if self.debug: print("Connected!") break except (RuntimeError, TypeError, adafruit_espatcontrol.OKError) as ex: if self.debug: print("EXCEPTION: Failed to publish()", repr(ex)) time.sleep(RECONNECT_SLEEP) ### This uses global variables socket.set_interface(self.esp) ### MQTT Client ### pylint: disable=protected-access self.mqtt_client = MQTT.MQTT(broker="io.adafruit.com", username=self.secrets["aio_username"], password=self.secrets["aio_key"], socket_pool=socket, ssl_context=MQTT._FakeSSLContext( self.esp)) self.io = IO_MQTT(self.mqtt_client) ### Callbacks of interest on io are ### on_connect on_disconnect on_subscribe self.io.connect() def reset_and_reconnect(self): self.wifi.reset() self.io.reconnect() def update_pub_name(self, field_name): pub_name = self.pub_prefix + field_name return pub_name def poll(self): dw_poll_ok = False try_reconnect = False for _ in range(2): try: ### Process any incoming messages if try_reconnect: self.reset_and_reconnect() try_reconnect = False self.io.loop() dw_poll_ok = True except (ValueError, RuntimeError, AttributeError, MQTT.MMQTTException, adafruit_espatcontrol.OKError, AdafruitIO_MQTTError) as ex: if self.debug: print("EXCEPTION: Failed to get data in loop()", repr(ex)) try_reconnect = True return dw_poll_ok def publish(self, p_data, p_fields): ok = [False] * len(p_fields) try_reconnect = False if self.debug: print("publish()") for idx, field_name in enumerate(p_fields): try: pub_name = self.pub_name[field_name] except KeyError: pub_name = self.update_pub_name(field_name) for _ in range(2): try: if try_reconnect: self.reset_and_reconnect() try_reconnect = False self.io.publish(pub_name, p_data[field_name]) ok[idx] = True break except (ValueError, RuntimeError, AttributeError, MQTT.MMQTTException, adafruit_espatcontrol.OKError, AdafruitIO_MQTTError) as ex: if self.debug: print("EXCEPTION: Failed to publish()", repr(ex)) try_reconnect = True time.sleep(RECONNECT_SLEEP) return all(ok)