Пример #1
0
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())
Пример #2
0
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
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
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")
Пример #6
0
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())
Пример #7
0
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())
Пример #8
0
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()
Пример #9
0
    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)
Пример #10
0
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()
Пример #11
0
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()
Пример #12
0
 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()) 
Пример #14
0
    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)
Пример #15
0
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",
    ))
Пример #16
0
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()
Пример #17
0
    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,))
Пример #18
0
    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, ))
Пример #19
0
    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,))
Пример #20
0
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()
Пример #21
0
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)
Пример #22
0
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()
Пример #23
0
            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)
Пример #24
0
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