def _composeDiscoveryMsg(component_topic, name, component_type_discovery, friendly_name=None, no_avail=False): """ Helper function to separate dynamic system values from user defineable values. :param component_topic: state topic of the component. device topics (see mqtt) are supported :param name: name of the component, must be unique on the device, typically composed of component name and count :param component_type_discovery: discovery values for the component type, e.g. switch, sensor :param friendly_name: optional a readable name that is used in the gui and entity_id :param no_avail: don't add availability configs (typically only used for the availability component itself) :return: str """ friendly_name = friendly_name or name component_topic = component_topic if _mqtt.isDeviceTopic( component_topic) is False else _mqtt.getRealTopic(component_topic) if no_avail is True: return DISCOVERY_BASE_NO_AVAIL.format( component_topic, # "~" component state topic friendly_name, # name sys_vars.getDeviceID(), name, # unique_id component_type_discovery, # component type specific values sys_vars.getDeviceDiscovery()) # device return DISCOVERY_BASE.format( component_topic, # "~" component state topic friendly_name, # name config.MQTT_HOME, sys_vars.getDeviceID(), # availability_topic sys_vars.getDeviceID(), name, # unique_id component_type_discovery, # component type specific values sys_vars.getDeviceDiscovery()) # device
async def asyncLog(name, message, level): if config.getMQTT() is not None: base_topic = "{!s}/log/{!s}/{!s}".format(config.MQTT_HOME, "{!s}", sys_vars.getDeviceID()) # if level is before id other clients can subscribe to e.g. all critical logs await config.getMQTT().publish(base_topic.format(level), "[{!s}] {}".format(name, message), qos=1) else: print(level, message)
async def _discovery(self, register=True): name = "{!s}{!s}".format(COMPONENT_NAME, self._count) base_topic = _mqtt.getRealTopic(_mqtt.getDeviceTopic(name)) modes = ujson.dumps([str(mode) for mode in self._modes]) gc.collect() if register: sens = CLIMATE_DISCOVERY.format( base_topic, self._frn or name, self._composeAvailability(), sys_vars.getDeviceID(), name, # unique_id _mqtt.getRealTopic( self.temp_sensor.getTopic(SENSOR_TEMPERATURE)), # current_temp_topic self.temp_sensor.getTemplate(SENSOR_TEMPERATURE), # cur_temp_template self._temp_step, self._min_temp, self._max_temp, modes, sys_vars.getDeviceDiscovery()) else: sens = "" gc.collect() topic = Component._getDiscoveryTopic(_COMPONENT_TYPE, name) await _mqtt.publish(topic, sens, qos=1, retain=True)
def __init__(self, receive_config=False): """ receive_config: False, if true tries to get the configuration of components from a server connected to the mqtt broker allow_wildcards: True, if false no subscriptions ending with "/#" are allowed; this also saves RAM as the module "subscription" is used as a backend to store subscriptions instead of the module "tree" which is bigger """ self.payload_on = ("ON", True, "True") self.payload_off = ("OFF", False, "False") self.client_id = sys_vars.getDeviceID() self.mqtt_home = config.MQTT_HOME super().__init__(client_id=self.client_id, server=config.MQTT_HOST, port=1883, user=config.MQTT_USER, password=config.MQTT_PASSWORD, keepalive=config.MQTT_KEEPALIVE, subs_cb=self._execute_sync, wifi_coro=self._wifiChanged, connect_coro=self._connected, will=(self.getRealTopic( self.getDeviceTopic("status")), "offline", True, 1), clean=False, ssid=config.WIFI_SSID, wifi_pw=config.WIFI_PASSPHRASE) asyncio.get_event_loop().create_task(self.connect()) self.__receive_config = receive_config # True=receive config, None=config received self._awaiting_config = False self._temp = [] # temporary storage for retained state topics gc.collect()
async def _discovery(self, register=True): topic = _mqtt.getRealTopic(_mqtt.getDeviceTopic("status")) if register: await self._publishDiscovery( "sensor", topic, "status", STATE_TYPE, "Status {!s}".format(config.DEVICE_NAME or sys_vars.getDeviceID())) else: await self._deleteDiscovery("sensor", "status") gc.collect()
async def asyncLog(name, level, *message, timeout=None, await_connection=True): if level == "debug" and not config.DEBUG: # ignore debug messages if debug is disabled return if config.getMQTT(): base_topic = "{!s}/log/{!s}/{!s}".format(config.MQTT_HOME, "{!s}", sys_vars.getDeviceID()) # if level is before id other clients can subscribe to e.g. all critical logs message = (b"{} " * (len(message) + 1)).format("[{}]".format(name), *message) gc.collect() await config.getMQTT().publish(base_topic.format(level), message, qos=1, timeout=timeout, await_connection=await_connection)
def __init__(self, receive_config=False): """ receive_config: False, if true tries to get the configuration of components from a server connected to the mqtt broker allow_wildcards: True, if false no subscriptions ending with "/#" are allowed; this also saves RAM as the module "subscription" is used as a backend to store subscriptions instead of the module "tree" which is bigger """ gc.collect() self.payload_on = ("ON", True, "True") self.payload_off = ("OFF", False, "False") self.client_id = sys_vars.getDeviceID() self.mqtt_home = config.MQTT_HOME super().__init__((self.getRealTopic(self.getDeviceTopic("status")), "OFFLINE", 1, True), (self.getRealTopic(self.getDeviceTopic("status")), "ONLINE", 1, True)) self.__receive_config = receive_config # True=receive config, None=config received self._awaiting_config = False
def __init__(self): self.payload_on = ("ON", True, "True") self.payload_off = ("OFF", False, "False") self.client_id = sys_vars.getDeviceID() self.mqtt_home = config.MQTT_HOME self._subs = [] self._sub_coro = None self._sub_retained = False super().__init__(client_id=self.client_id, server=config.MQTT_HOST, port=config.MQTT_PORT if hasattr(config, "MQTT_PORT") is True else 1883, user=config.MQTT_USER, password=config.MQTT_PASSWORD, keepalive=config.MQTT_KEEPALIVE, subs_cb=self._execute_sync, wifi_coro=self._wifiChanged, connect_coro=self._connected, will=(self.getRealTopic( self.getDeviceTopic( config.MQTT_AVAILABILITY_SUBTOPIC)), "offline", True, 1), clean=False, ssid=config.WIFI_SSID, wifi_pw=config.WIFI_PASSPHRASE) asyncio.get_event_loop().create_task(self._connectCaller()) self.__first_connect = True self._connected_coro = None self._reconnected_subs = [] self._wifi_coro = None self._wifi_subs = [] self._ops_coros = [ None, None ] # publish and (un)sub operations, can be concurrently self.__unsub_tmp = [] self.__last_disconnect = None # ticks_ms() of last disconnect self.__downtime = 0 # mqtt downtime in seconds self.__reconnects = -1 # not counting the first connect self.__dropped = 0 # dropped messages due to waitq being too full self.__timedout = 0 # operations that timed out. doesn't mean it's a problem. self.__active_cbs = 0 # currently active callbacks due to received messages gc.collect()
def _getDiscoveryTopic(component_type, name): return "{!s}/{!s}/{!s}/{!s}/config".format( config.MQTT_DISCOVERY_PREFIX, component_type, sys_vars.getDeviceID(), name)
def _composeAvailability(): return DISCOVERY_AVAILABILITY.format(config.MQTT_HOME, sys_vars.getDeviceID(), config.MQTT_AVAILABILITY_SUBTOPIC)
def __init__(self): self.id = sys_vars.getDeviceID() self.base_topic = "{!s}/log/{!s}/{!s}".format(config.MQTT_HOME, "{!s}", sys_vars.getDeviceID())
from pysmartnode import config import gc import uasyncio as asyncio from pysmartnode.utils.sys_vars import getDeviceID import network __updated__ = "2020-08-19" try: s = network.WLAN(network.STA_IF) s.config(dhcp_hostname="{}{}".format("ESP32_", getDeviceID())) except Exception as e: print(e) # not important enough to do anything about it if config.RTC_SYNC_ACTIVE: from .ntp import sync asyncio.create_task(sync()) gc.collect() if hasattr(config, "FTP_ACTIVE") and config.FTP_ACTIVE is True: if config.WEBREPL_ACTIVE is True: try: import _thread except: config._log.critical( "ftpserver background can't be used with webrepl") else: print("FTP-Server active") import pysmartnode.libraries.ftpserver.ftp_thread else:
from micropython_iot_generic.client.apps.mqtt import Mqtt from micropython_iot import Lock, Event from machine import Pin gc.collect() import uasyncio as asyncio import os import sys _log = logging.getLogger("MQTT") gc.collect() type_gen = type((lambda: (yield))()) # Generator type app_handler = apphandler.AppHandler(asyncio.get_event_loop(), sys_vars.getDeviceID(), config.MQTT_HOST, 8888, timeout=3000, verbose=True, led=Pin(2, Pin.OUT, value=1)) # TODO: update to support new APIs like mqtt_direct class MQTTHandler(Mqtt): def __init__(self, receive_config=False): """ receive_config: False, if true tries to get the configuration of components from a server connected to the mqtt broker allow_wildcards: True, if false no subscriptions ending with "/#" are allowed;
from micropython_iot_generic.client import apphandler from micropython_iot_generic.client.apps.mqtt import Mqtt from micropython_iot import Lock, Event from machine import Pin gc.collect() import uasyncio as asyncio import os import sys _log = logging.getLogger("MQTT") gc.collect() type_gen = type((lambda: (yield))()) # Generator type app_handler = apphandler.AppHandler(asyncio.get_event_loop(), sys_vars.getDeviceID(), config.MQTT_HOST, 8888, timeout=3000, verbose=True, led=Pin(2, Pin.OUT, value=1)) # TODO: update to support new APIs like mqtt_direct class MQTTHandler(Mqtt): def __init__(self, receive_config=False): """ receive_config: False, if true tries to get the configuration of components from a server connected to the mqtt broker allow_wildcards: True, if false no subscriptions ending with "/#" are allowed; this also saves RAM as the module "subscription" is used as a backend to store subscriptions instead of the module "tree" which is bigger