def test_btn(suppress=False, lf=True, df=True): s = ''' press pulses red release pulses green double click pulses yellow long press pulses blue ''' print('Test of pushbutton scheduling coroutines.') print(helptext) print(s) pin = Pin('X1', Pin.IN, Pin.PULL_UP) red = LED(1) green = LED(2) yellow = LED(3) blue = LED(4) pb = Pushbutton(pin, suppress) pb.press_func(pulse, (red, 1000)) pb.release_func(pulse, (green, 1000)) if df: print('Doubleclick enabled') pb.double_func(pulse, (yellow, 1000)) if lf: print('Long press enabled') pb.long_func(pulse, (blue, 1000)) loop = asyncio.get_event_loop() loop.run_until_complete(killer())
class LED(HomieNode): def __init__(self, name="Onboard LED", pin=2): super().__init__(id="led", name=name, type="LED") self.pin = pin self.led = Pin(pin, Pin.OUT, value=0) self.btn = Pushbutton(Pin(0, Pin.IN, Pin.PULL_UP)) self.btn.press_func(self.toggle_led) self.power_property = HomieNodeProperty( id="power", name="LED Power", settable=True, datatype=BOOLEAN, default=TRUE, ) self.add_property(self.power_property, self.on_power_msg) def on_power_msg(self, topic, payload, retained): self.led(ONOFF[payload]) self.power_property.data = ONOFF[self.led()] def toggle_led(self): if self.power_property.data != TRUE: self.led(0) self.power_property.data = TRUE else: self.led(1) self.power_property.data = FALSE
def __init__(self, *args, **kwargs): print("Initializing button") super().__init__(*args, **kwargs) self.pin = machine.Pin(self.settings["pin"], machine.Pin.IN) self.pushbutton = Pushbutton(self.pin) self.pushbutton.press_func(self.button_pressed)
def __init__(self, screens): self.screens = screens if not self.screens: self.screens = [DemoScreen()] self._screen = 0 # OLED spi = SPI(2, baudrate=14500000, sck=Pin(PIN_DISPLAY_CLK), mosi=Pin(PIN_DISPLAY_MOSI)) self.display = SafeDisplay(spi, dc=Pin(PIN_DISPLAY_DC), cs=Pin(PIN_DISPLAY_CS), rst=Pin(PIN_DISPLAY_RST)) loop = asyncio.get_event_loop() loop.create_task(self.update_display()) # Encoder rotation self.encoder = RotaryEncoder(PIN_KNOB_CLK, PIN_KNOB_DT, cw=self.encoder_cw, ccw=self.encoder_ccw) # Encoder button self.button = Pushbutton(Pin(PIN_KNOB_SWITCH, Pin.IN)) self.button.release_func(self.encoder_push) self.button.double_func(self.encoder_dblpush) self.button.long_func(self.encoder_longpush)
class Button(Module): def __init__(self, *args, **kwargs): print("Initializing button") super().__init__(*args, **kwargs) self.pin = machine.Pin(self.settings["pin"], machine.Pin.IN) self.pushbutton = Pushbutton(self.pin) self.pushbutton.press_func(self.button_pressed) def button_pressed(self, timer=None): print("Button pressed") self.parent.call_callbacks("button_on_pressed_callback")
def test_btncb(): print('Test of pushbutton executing callbacks.') print(helptext) pin = Pin('X1', Pin.IN, Pin.PULL_UP) red = LED(1) green = LED(2) yellow = LED(3) blue = LED(4) pb = Pushbutton(pin) pb.press_func(toggle, (red, )) pb.release_func(toggle, (green, )) pb.double_func(toggle, (yellow, )) pb.long_func(toggle, (blue, )) loop = asyncio.get_event_loop() loop.run_until_complete(killer())
def test_btn(): print('Test of pushbutton scheduling coroutines.') print(helptext) pin = Pin('X1', Pin.IN, Pin.PULL_UP) red = LED(1) green = LED(2) yellow = LED(3) blue = LED(4) pb = Pushbutton(pin) pb.press_func(pulse, (red, 1000)) pb.release_func(pulse, (green, 1000)) pb.double_func(pulse, (yellow, 1000)) pb.long_func(pulse, (blue, 1000)) loop = asyncio.get_event_loop() loop.run_until_complete(killer())
class SmartSocket(HomieNode): def __init__(self): super().__init__(id="relay", name="Wifi Power Socket", type="OW8266-02Q") self.led = Pin(4, Pin.OUT, value=1) self.r_on = Pin(12, Pin.OUT) self.r_off = Pin(5, Pin.OUT) self.relay_property = HomieNodeProperty( id="power", name="Relay", settable=True, retained=True, datatype="bool", default=FALSE, restore=True, ) self.add_property(self.relay_property) self.button = Pushbutton(Pin(14, Pin.IN, Pin.PULL_UP)) self.button.release_func(self.toggle, ()) self.button.long_func(reset, (self.led, )) def off(self): self.r_off(0) sleep_ms(100) self.r_on(1) self.relay_property.data = FALSE def on(self): self.r_on(0) sleep_ms(100) self.r_off(1) self.relay_property.data = TRUE def callback(self, topic, payload, retained): if b"power" in topic: if payload == FALSE: self.off() elif payload == TRUE: self.on() def toggle(self): if self.relay_property.data == TRUE: self.off() else: self.on()
def __init__(self, name="Onboard LED", pin=2): super().__init__(id="led", name=name, type="LED") self.pin = pin self.led = Pin(pin, Pin.OUT, value=0) self.btn = Pushbutton(Pin(0, Pin.IN, Pin.PULL_UP)) self.btn.press_func(self.toggle_led) self.power_property = HomieNodeProperty( id="power", name="LED Power", settable=True, datatype=BOOLEAN, default=TRUE, ) self.add_property(self.power_property, self.on_power_msg)
class SmartSocket(HomieNode): def __init__(self, name="Relay 16A"): super().__init__(id="relay", name=name, type="Gosund SP1") # disable REPL so we can use the blue led uos.dupterm(None, 1) self.led_b = Pin(1, Pin.OUT, value=1) # Blue LED self.led_r = Pin(13, Pin.OUT, value=1) # Red LED self.relay = Pin(14, Pin.OUT) self.power_property = HomieNodeProperty( id="power", name="Power", settable=True, datatype=BOOLEAN, default=FALSE, ) self.add_property(self.power_property, self.on_power_msg) self.button = Pushbutton(Pin(3, Pin.IN)) self.button.release_func(self.toggle, ()) self.button.long_func(reset, (self.led_r,)) def off(self): self.relay(0) self.led_b(0) self.led_r(1) self.power_property.data = FALSE def on(self): self.relay(1) self.led_b(1) self.led_r(0) self.power_property.data = TRUE def on_power_msg(self, topic, payload, retained): if payload == FALSE: self.off() elif payload == TRUE: self.on() def toggle(self): if self.power_property.data == TRUE: self.off() else: self.on()
class SmartSocket(HomieNode): def __init__(self): super().__init__(id="relay", name="Relay 16A", type="Gosund SP1 v23") uos.dupterm(None, 1) # disable REPL so we can use the blue led self.led_b = Pin(1, Pin.OUT, value=1) self.led_r = Pin(13, Pin.OUT, value=1) self.relay = Pin(14, Pin.OUT) self.relay_property = HomieNodeProperty( id="power", name="Relay", settable=True, retained=True, datatype="boolean", default=FALSE, restore=True, ) self.add_property(self.relay_property) self.button = Pushbutton(Pin(3, Pin.IN)) self.button.release_func(self.toggle, ()) self.button.long_func(reset, (self.led_r,)) def off(self): self.relay(0) self.led_b(0) self.led_r(1) self.relay_property.data = FALSE def on(self): self.relay(1) self.led_b(1) self.led_r(0) self.relay_property.data = TRUE def callback(self, topic, payload, retained): if b"power" in topic: if payload == FALSE: self.off() elif payload == TRUE: self.on() def toggle(self): if self.relay_property.data == TRUE: self.off() else: self.on()
def init(self, plugin, device, queue, scriptqueue): self._log.debug("Plugin: switch init") # generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue) self.content = plugin.get('content', content) self.pincnt = pincnt self.valuecnt = valuecnt self.stype = stype plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(self.devicename) # plugin specific section self.switch_status = bootstate if self.inputtype == 'normal': self._log.debug("Plugin: switch init normal, pin: " + self.dxpin) # Setup switch self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Switch(self.swpin) # Register coros to launch on contact close and open self.switch.close_func(self.asyncswitchopen) self.switch.open_func(self.asyncswitchclosed) elif self.inputtype == 'low': self._log.debug("Plugin: switch init low, pin: " + self.dxpin) # Setup button active low self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) else: self._log.debug("Plugin: switch init high, pin: " + self.dxpin) # Setup button active high self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_DOWN) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) return True
def __init__(self): log.info('DISP:init') self.screens = [self.show_measurement_screen, self.show_decibel_screen, self.show_environmental_screen, self.show_voltage_monitor_screen, self.show_display_sleep_screen] pin_screen = Pin(0, Pin.IN, Pin.PULL_UP) pb_screen = Pushbutton(pin_screen) pb_screen.press_func(self.next_screen) self.active_screen = 1 # TODO make some sort of datastructure for screens + screen ids self.next_screen = 0 # show the measurement screen first TODO this is a clunky way to show this after measurement screen self.diag_count = 0 self.screen_timeout = False self.timeout_timer = Timer(-1) self.backlight_ctrl = Pin(2, Pin.OUT) self.backlight_ctrl.value(0) loop = asyncio.get_event_loop() loop.create_task(self.run_display())
def saveform(self, plugindata): self._log.debug("Plugin: switch saveform") # generic section self._utils.plugin_saveform(self, plugindata) # plugin specific section self.inputtype = plugindata['inputtype'] self.dxpin = plugindata['dxpin0'] # store values data = {} data["inputtype"] = self.inputtype data["dxpin"] = self.dxpin data["valueN1"] = self.valuenames["valueN1"] data["valueF1"] = self.valuenames["valueF1"] data["valueD1"] = self.valuenames["valueD1"] self._plugins.writestore(self.devicename, data) if self.inputtype == 'normal': # Setup switch self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Switch(self.swpin) # Register coros to launch on contact close and open self.switch.close_func(self.asyncswitchopen) self.switch.open_func(self.asyncswitchclosed) elif self.inputtype == 'low': # Setup button active low self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) else: # Setup button active high self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_DOWN) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong)
async def test_btn(pin, suppress=True, lf=True, df=True): ''' handler for aswitch.Pushbutton instances ''' pb = Pushbutton(pin, suppress) print('{} set up'.format(pin)) pb.press_func(button_operation, ( str(pin), "pushed", )) pb.release_func(button_operation, ( str(pin), "released", )) pb.double_func(button_operation, ( str(pin), "double-clicked", )) pb.long_func(button_operation, ( str(pin), "long pressed", ))
async def main(): global thermo set_global_exception() # Debug aid switch = Pushbutton(sw, suppress=True) switch.release_func(switch_display, ()) uasyncio.create_task(thermo.blink()) # Or you might do this #uasyncio.create_task(thermo.temp()) uasyncio.create_task(thermo.temp_thermo()) uasyncio.create_task(thermo.encoder_loop(enc)) uasyncio.create_task(thermo.calc_diff()) uasyncio.create_task(thermo.alert_check()) uasyncio.create_task(thermo.alert_light()) uasyncio.create_task(thermo.show_lcd_initial() ) #makes sure that something shows up initially #await thermo.cancel() # Non-terminating method await thermo.temp()
def __init__(self): super().__init__(id="relay", name="Relay 16A", type="Gosund SP1 v23") uos.dupterm(None, 1) # disable REPL so we can use the blue led self.led_b = Pin(1, Pin.OUT, value=1) self.led_r = Pin(13, Pin.OUT, value=1) self.relay = Pin(14, Pin.OUT) self.relay_property = HomieNodeProperty( id="power", name="Relay", settable=True, retained=True, datatype="boolean", default=FALSE, restore=True, ) self.add_property(self.relay_property) self.button = Pushbutton(Pin(3, Pin.IN)) self.button.release_func(self.toggle, ()) self.button.long_func(reset, (self.led_r,))
def __init__(self): super().__init__(id="relay", name="Wifi Power Socket", type="OW8266-02Q") self.led = Pin(4, Pin.OUT, value=1) self.r_on = Pin(12, Pin.OUT) self.r_off = Pin(5, Pin.OUT) self.relay_property = HomieNodeProperty( id="power", name="Relay", settable=True, retained=True, datatype="bool", default=FALSE, restore=True, ) self.add_property(self.relay_property) self.button = Pushbutton(Pin(14, Pin.IN, Pin.PULL_UP)) self.button.release_func(self.toggle, ()) self.button.long_func(reset, (self.led, ))
def __init__(self, name="Relay 16A"): super().__init__(id="relay", name=name, type="Gosund SP1") # disable REPL so we can use the blue led uos.dupterm(None, 1) self.led_b = Pin(1, Pin.OUT, value=1) # Blue LED self.led_r = Pin(13, Pin.OUT, value=1) # Red LED self.relay = Pin(14, Pin.OUT) self.power_property = HomieNodeProperty( id="power", name="Power", settable=True, datatype=BOOLEAN, default=FALSE, ) self.add_property(self.power_property, self.on_power_msg) self.button = Pushbutton(Pin(3, Pin.IN)) self.button.release_func(self.toggle, ()) self.button.long_func(reset, (self.led_r,))
class ScooterDisplay(object): def __init__(self, screens): self.screens = screens if not self.screens: self.screens = [DemoScreen()] self._screen = 0 # OLED spi = SPI(2, baudrate=14500000, sck=Pin(PIN_DISPLAY_CLK), mosi=Pin(PIN_DISPLAY_MOSI)) self.display = SafeDisplay(spi, dc=Pin(PIN_DISPLAY_DC), cs=Pin(PIN_DISPLAY_CS), rst=Pin(PIN_DISPLAY_RST)) loop = asyncio.get_event_loop() loop.create_task(self.update_display()) # Encoder rotation self.encoder = RotaryEncoder(PIN_KNOB_CLK, PIN_KNOB_DT, cw=self.encoder_cw, ccw=self.encoder_ccw) # Encoder button self.button = Pushbutton(Pin(PIN_KNOB_SWITCH, Pin.IN)) self.button.release_func(self.encoder_push) self.button.double_func(self.encoder_dblpush) self.button.long_func(self.encoder_longpush) def encoder_cw(self, steps): print("DISPLAY: Encoder CW, {} steps".format(steps)) self._screen += 1 if self._screen > len(self.screens) - 1: self._screen = 0 def encoder_ccw(self, steps): print("DISPLAY: Encoder CCW, {} steps".format(steps)) self._screen -= 1 if self._screen < 0: self._screen = len(self.screens) - 1 def encoder_push(self): print("DISPLAY: Encoder PUSH") self.screens[self._screen].encoder_click() def encoder_dblpush(self): print("DISPLAY: Encoder DBLPUSH") self.screens[self._screen].encoder_dblclick() def encoder_longpush(self): print("DISPLAY: Encoder LONGPUSH") self.screens[self._screen].encoder_longpress() async def update_display(self): current_screen = self._screen screen_changed = True needs_pixel_shift = False while True: if screen_changed or needs_pixel_shift: self.display.clear() if needs_pixel_shift: self.screens[self._screen].pixel_shift() self.screens[self._screen].update(self.display, needs_full_redraw=screen_changed or needs_pixel_shift) current_screen = self._screen await asyncio.sleep_ms(1000) screen_changed = current_screen != self._screen needs_pixel_shift = self.screens[self._screen].needs_pixel_shift()
class SmartPlug(object): led = Signal(Pin(LED, Pin.OUT, value=0), invert=True) relay = Signal(Pin(RELAY, Pin.OUT, value=0)) button = Pushbutton(Pin(BUTTON, Pin.IN)) # default value so that .log() works even before mqtt has been created mqtt = None def __init__(self, topic): assert isinstance(topic, bytes) self.topic = topic self.log_topic = topic + b'/log' self.wifi_connected = False # # initialize status BEFORE starting mqtt: this way, as soon as the # first retained message arrives, we are ready to handle it self.set_status(False, should_publish=False) self.status_received = False self.mqtt = MQTTClient( server=SERVER, keepalive=120, clean=True, clean_init=True, subs_cb=self.on_receive_topic, ) self.button.press_func(self.on_click) self.button.long_func(self.on_long_press) self.button.double_func(self.on_double_click) def log(self, *args): msg = '[%s] %s' % (fmtime(), ' '.join(map(str, args))) print(msg) if self.mqtt: LOOP.create_task(self.mqtt.publish(self.log_topic, msg)) @property def status(self): """ The status of the switch. The invariant is that the following are always in sync: - the status led - the relay - the mqtt topic (which is retained) """ return self._status def set_status(self, v, should_publish): self.log("[STAT] set status to", v) self._status = v self.led.value(v) self.relay.value(v) if should_publish: self.publish_status() def publish_status(self): msg = str(int(self.status)) self.log('[PUB ]', self.topic, msg) LOOP.create_task( self.mqtt.publish(self.topic, msg, retain=True, qos=QOS_AT_LEAST)) def on_receive_topic(self, topic, msg): self.log('[SUB ] received', topic, msg) if topic == self.topic: try: value = int(msg) except ValueError: self.log('[SUB ] invalid value, defaulting to 0') value = 0 # self.status_received = True if self.status == value: self.log("[SUB ] status already %s, ignoring" % value) return self.log('[SUB ] setting status to', value) self.set_status(value, should_publish=False) def on_click(self): self.set_status(not self.status, should_publish=True) def on_long_press(self): print('long press') def on_double_click(self): print('double click') async def wait_for_connection(self): self.log('[MQTT] Connecting...') sta_if = WLAN(STA_IF) conn = False while not conn: while not sta_if.isconnected(): self.log('[MQTT] Waiting for WiFi...') await asyncio.sleep(1) self.wifi_connected = True self.log('[MQTT] WiFi connected, waiting some more...') await asyncio.sleep(3) try: await self.mqtt.connect() conn = True except OSError: self.mqtt.close() # Close socket self.log('[MQTT] Waiting for server...') self.log('[MQTT] Connected') await self.mqtt.subscribe(self.topic, QOS_AT_LEAST) def robust_ntptime_set(self): import ntptime try: ntptime.settime() except Exception as e: self.log('[TIME] caught exception inside ntptime, ignoring') sys.print_exception(e) print() return False else: return True async def timer(self): import ntptime # first, wait for wifi connection and set time while not self.wifi_connected: self.log('[TIME] Waiting for Wifi...') await asyncio.sleep(1) # is_time_correct = False previous_desired_state = None while True: self.log('[TIME] setting NTP time') if self.robust_ntptime_set(): is_time_correct = True self.log('[TIME] UTC time: %s' % fmtime()) else: # note: we do NOT want to set is_time_correct: we assume that # after the first time we set the time, it will stay "correct" print('[TIME] cannot set NTP time') # if not is_time_correct: self.log('[TIME] time not reliable, retrying...') await asyncio.sleep(1) continue # t = time.time() y, m, d, hh, mm, ss = time.localtime(t)[:6] # turn the lights on between 17 and 1 CEST, i.e. 16-24 UTC desired_state = hh >= 16 if desired_state != previous_desired_state: self.log('[TIME] changing status') self.set_status(desired_state, should_publish=True) previous_desired_state = desired_state # # now, determine how much to sleep before next change if desired_state: # wait until next day: to determine it, we do 23:59:59 + 1 second t_end = time.mktime((y, m, d, 23, 59, 59, None, None)) + 1 else: # wait until 16 of the current day t_end = time.mktime((y, m, d, 16, 0, 0, None, None)) t_diff = t_end - t t_diff = min(t_diff, 1 * 60) # sleep at max 10 minutes self.log('[TIME] sleeping for %d seconds, until %s' % (t_diff, fmtime(t + t_diff))) await asyncio.sleep(t_diff) self.log('[TIME] woke up at %s' % fmtime()) async def main(self): LOOP.create_task(self.wait_for_connection()) LOOP.create_task(self.timer()) i = 0 while True: self.log('[MAIN]', i) mem_info() # # periodically publish the status, but ONLY if we received at # least one message from the broker. Else, at startup we send 0 # before we had the chance to receive the reatined message if self.status_received: self.publish_status() i += 1 await asyncio.sleep(60)
class switch_plugin: inputtype = "normal" # Default switch type datastore = None # Place where plugin data is stored for reboots def __init__(self): # generic section self._log = core._log self._log.debug("Plugin: switch contruction") self._utils = core._utils self._plugins = core._plugins self._hal = core._hal self._lock = Event() self.dxpin = dxpin # plugin specific section self.valuenames = {} self.valuenames["valueN1"] = "switch" self.valuenames["valueF1"] = "" self.valuenames["valueD1"] = 0 # release lock, ready for next measurement self._lock.clear() def init(self, plugin, device, queue, scriptqueue): self._log.debug("Plugin: switch init") # generic section self._utils.plugin_initdata(self, plugin, device, queue, scriptqueue) self.content = plugin.get('content', content) plugin['dtype'] = dtype plugin['stype'] = stype plugin['template'] = template datastore = self._plugins.readstore(self.devicename) # plugin specific section self.switch_status = bootstate if self.inputtype == 'normal': self._log.debug("Plugin: switch init normal, pin: " + self.dxpin) # Setup switch self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Switch(self.swpin) # Register coros to launch on contact close and open self.switch.close_func(self.asyncswitchopen) self.switch.open_func(self.asyncswitchclosed) elif self.inputtype == 'low': self._log.debug("Plugin: switch init low, pin: " + self.dxpin) # Setup button active low self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) else: self._log.debug("Plugin: switch init high, pin: " + self.dxpin) # Setup button active high self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_DOWN) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) return True def loadform(self, plugindata): self._log.debug("Plugin: switch loadform") # generic section self._utils.plugin_loadform(self, plugindata) # plugin specific section plugindata['inputtype'] = self.inputtype plugindata['dxpin0'] = self.dxpin def saveform(self, plugindata): self._log.debug("Plugin: switch saveform") # generic section self._utils.plugin_saveform(self, plugindata) # plugin specific section self.inputtype = plugindata['inputtype'] self.dxpin = plugindata['dxpin0'] # store values data = {} data["inputtype"] = self.inputtype data["dxpin"] = self.dxpin data["valueN1"] = self.valuenames["valueN1"] data["valueF1"] = self.valuenames["valueF1"] data["valueD1"] = self.valuenames["valueD1"] self._plugins.writestore(self.devicename, data) if self.inputtype == 'normal': # Setup switch self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Switch(self.swpin) # Register coros to launch on contact close and open self.switch.close_func(self.asyncswitchopen) self.switch.open_func(self.asyncswitchclosed) elif self.inputtype == 'low': # Setup button active low self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_UP) self.switch = Pushbutton(self.swpin) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) else: # Setup button active high self.swpin = self._hal.pin(self.dxpin, core.PIN_IN, core.PIN_PULL_DOWN) self.switch.press_func(self.asyncbuttonpress) self.switch.release_func(self.asyncbuttonrelease) self.switch.double_func(self.asyncbuttondouble) self.switch.long_func(self.asyncbuttonlong) def read(self, values): self._log.debug("Plugin: switch read") # generic section values['valueN1'] = self.valuenames["valueN1"] values['valueD1'] = self.switch_status def write(self, values): self._log.debug("Plugin: switch write") async def asyncprocess(self): self._log.debug("Plugin: switch process") # plugin specific section # If a switch occured if self.switch_status: # send data to protocol and script/rule queues self.valuenames["valueD1"] = self.switch_status self._utils.plugin_senddata(self) # erase status self.switch_status = "" # release lock, ready for next measurement self._lock.clear() # #CUSTOM SENSOR CODE... # async def asyncswitchopen(self): self.switch_status = 'open' # release lock, ready for next measurement self._lock.clear() async def asyncswitchclosed(self): self.switch_status = 'closed' # release lock, ready for next measurement self._lock.clear() async def asyncbuttonpress(self): self.switch_status = 'press' # release lock, ready for next measurement self._lock.clear() async def asyncbuttonrelease(self): self.switch_status = 'release' # release lock, ready for next measurement self._lock.clear() async def asyncbuttondouble(self): self.switch_status = 'double' # release lock, ready for next measurement self._lock.clear() async def asyncbuttonlong(self): self.switch_status = 'long' # release lock, ready for next measurement self._lock.clear()
if x != 0x01: try: i2c2.start() data[0] = x << 1 data[1] = 0x01 data[2] = userHCScore >> 8 data[3] = userHCScore i2c2.write(data) i2c2.stop() except: pass await asyncio.sleep(60) upBtn = Pushbutton(upPin) downBtn = Pushbutton(downPin) selectBtn = Pushbutton(selectPin) upBtn.press_func(buttonPressed, (1, )) downBtn.press_func(buttonPressed, (2, )) selectBtn.press_func(buttonPressed, (3, )) upBtn.debounce_ms = 100 def startWifi(): global userHCScore wifi_config.start_wifi() if wifi_config.is_wifi_connected(): userHCScore = hc.get_score(hcid)
class Sonoff(MQTTClient): led = Signal(Pin(13, Pin.OUT, value=1), invert=True) relay = Pin(12, Pin.OUT, value=0) button = Pushbutton(Pin(0, Pin.IN)) # Pin 5 on serial connector is GPIO14. Pullup in case n/c pin5 = Pin(14, Pin.IN, pull=Pin.PULL_UP) def __init__(self, dict_topics): self.topics = dict_topics # OVERRIDE CONFIG DEFAULTS. # Callbacks & coros. config['subs_cb'] = self.sub_cb config['wifi_coro'] = self.wifi_han config['connect_coro'] = self.conn_han # MQTT. will_topic = self.topics['will'] if will_topic is not None: config['will'] = (will_topic, 'Goodbye from Sonoff!', False, 0) config['server'] = SERVER config['keepalive'] = 120 # Setting clean False ensures that commands sent during an outage will be honoured # when connectivity resumes. config['clean'] = True config['clean_init'] = True # ping_interval = 5 ensures that LED starts flashing promptly on an outage. # This interval is much too fast for a public broker on the WAN. # config['ping_interval'] = 5 super().__init__(config) if self.topics['button'] is not None: # CONFIGURE PUSHBUTTON self.button.press_func(self.btn_action, ('Button press', )) self.button.long_func(self.btn_action, ('Long press.', )) self.button.double_func(self.btn_action, ('Double click.', )) self.led_state = 0 self.outage = True self.outages = 0 self.outage_start = ticks_ms() self.max_outage = 0 if self.topics['remote'] is not None: self.ir = NEC_IR(self.pin5, self.rc_cb, True) # Publish a message if WiFi and broker is up, else discard. def pub_msg(self, topic_name, msg): topic = self.topics[topic_name] if topic is not None and not self.outage: loop.create_task(self.publish(topic, msg, qos=QOS)) # Callback for message from IR remote. def rc_cb(self, data, addr): if data == REPEAT: msg = 'RC:,Repeat' elif data >= 0: msg = ','.join(('RC:', hex(data), hex(addr))) else: msg = ','.join(('RC:,Error', str(data))) self.pub_msg('remote', msg) # Callback for all pushbutton actions. def btn_action(self, msg): self.pub_msg('button', msg) # Callback for subscribed messages def sub_cb(self, topic, msg): if topic == self.topics['relay']: if msg == M_ON or msg == M_OFF: self.relay(int(msg == M_ON)) elif topic == self.topics['led']: if msg == M_ON or msg == M_OFF: self.led_state = int(msg == M_ON) # Callback when connection established. Create subscriptions. async def conn_han(self, _): led_topic = self.topics['led'] if led_topic is not None: await self.subscribe(led_topic, QOS) relay_topic = self.topics['relay'] if relay_topic is not None: await self.subscribe(relay_topic, QOS) self.pub_msg('debug', '(Re)connected to broker.') # Callback for changes in WiFi state. async def wifi_han(self, state): self.outage = not state if state: duration = ticks_diff(ticks_ms(), self.outage_start) // 1000 self.max_outage = max(self.max_outage, duration) self.pub_msg('debug', 'Network up after {}s down.'.format(duration)) else: # Little point in publishing "Network Down" self.outages += 1 self.outage_start = ticks_ms() await asyncio.sleep(1) # Flash LED if WiFi down, otherwise reflect its current state. async def led_ctrl(self): while True: if self.outage: self.led(not self.led()) await asyncio.sleep_ms(200) else: self.led(self.led_state) await asyncio.sleep_ms(50) # Code assumes ESP8266 has stored the WiFi credentials in flash. async def main(self): loop.create_task(self.led_ctrl()) sta_if = WLAN(STA_IF) conn = False while not conn: while not sta_if.isconnected(): await asyncio.sleep(1) self.dprint('Awaiting WiFi.' ) # Repeats forever if no stored connection. await asyncio.sleep(3) try: await self.connect() conn = True except OSError: self.close() # Close socket self.dprint('Awaiting broker.') self.dprint('Starting.') self.outage = False n = 0 while True: await asyncio.sleep(60) gc.collect() # For RAM stats. msg = 'Mins: {} repubs: {} outages: {} RAM free: {} alloc: {} Longest outage: {}s'.format( n, self.REPUB_COUNT, self.outages, gc.mem_free(), gc.mem_alloc(), self.max_outage) self.pub_msg('debug', msg) n += 1