Esempio n. 1
0
 async def adjust_time(self, once=False):
     while True:
         self.get_time(set_rtc=True)
         if once:
             break
         await uasyncio.sleep(600)
         manage_memory()
Esempio n. 2
0
    def __init__(self, device, conf):
        RelaySwitchController.__init__(self, device, conf)
        self._power_monitor = None
        if conf.get('power_monitor'):
            manage_memory()
            from power_monitor import PowerMonitor
            try:
                self._power_monitor = PowerMonitor(conf['power_monitor'],
                                                   device.i2c)
            except Exception as exc:
                LOG.exc(exc, 'Power monitor init error')

        self._reverse = Pin(conf['reverse'], Pin.INOUT)
        self.reverse = False
        self._reverse_threshold = device.settings.get('reverse_threshold')
        self._reverse_duration = device.settings.get('reverse_duration')
        self._expired_limit = device.settings.get('expired_limit')
        self._reverse_delay = 2
        self._delay = 0
        self.flag_pins = None
        if conf.get('buttons'):
            self._buttons = []
            for idx, pin in enumerate(conf['buttons']):
                reverse = bool(idx)
                self._buttons.append(
                    Pin(pin,
                        Pin.IN,
                        Pin.PULL_UP,
                        handler=self.on_button_reverse
                        if reverse else self.on_button,
                        trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING))
        if conf.get('flag_pins'):
            self.flag_pins = [
                Pin(pin, Pin.IN, Pin.PULL_UP) for pin in conf['flag_pins']
            ]
 async def post_sensor_data(self, once=False):
     while True:
         if not once:
             await uasyncio.sleep(58)
         try:
             data = {'data': []}
             tstamp = self.post_tstamp()
             for ctrl in self.modules.values():
                 if ctrl and hasattr(ctrl, 'data_log'):
                     data['data'] += [{'sensor_id': entry[0], 'tstamp': entry[1], 'value': entry[2]}\
                         for entry in ctrl.data_log]
                 elif ctrl and hasattr(ctrl, 'data'):
                     data['data'] += [{'sensor_id': _id, 'tstamp': tstamp, 'value': value}\
                         for _id, value in ctrl.data.items()]
             if data['data']:
                 rsp = await self.srv_post('sensors_data', data, retry=once)
                 if once and not rsp:
                     machine.reset()
                 if rsp:
                     for ctrl in self.modules.values():
                         if ctrl and hasattr(ctrl, 'data_log'):
                             ctrl.data_log = []
             data = {'data': []}
             tstamp = self.post_tstamp()
             for ctrl in self.modules.values():
                 if ctrl and hasattr(ctrl, 'switches'):
                     data['data'] += [{'device_type_switch_id': switch['id'], 'tstamp': tstamp, 'state': switch['pin'].value() == 1}\
                         for switch in ctrl.switches.values() if switch['enabled']]
             if data['data']:
                 await self.srv_post('switches_state', data, retry=once)
         except Exception as exc:
             LOG.exc(exc, 'Server sensors data post error')
         manage_memory()
         if once:
             break
Esempio n. 4
0
 def on(self, value=True, manual=False):
     if self.state != value:
         if self._pulse_length:
             self._on = value
         else:
             self.pin.value(value)
         self.log_relay_switch('start' if value else 'stop',
                               'manual' if manual else 'timer')
     manage_memory()
Esempio n. 5
0
    async def check_timers(self):
        off = None
        while True:
            time = time_tuple_to_seconds(machine.RTC().now())
            if time == 0:
                self.init_timers()
            for timer in self.timers:
                if timer.time_on <= time < timer.time_on + timer.duration:
                    start = utime.time()
                    now = start
                    prev_time = start
                    expired = time - timer.time_on
                    retries = 0
                    self.on(source=timer)

                    def continue_flag():
                        nonlocal retries, expired
                        if retries >= 3:
                            return False
                        if self._expired_limit and expired > self._expired_limit:
                            return False
                        if timer.duration > 0 and expired > timer.duration:
                            return False
                        if self.flag_pins:
                            flag_pin = self.flag_pins[1 if self.reverse else 0]
                            if flag_pin.value():
                                self.device.append_log_entries(
                                    "%s task success" % self._timers_param)
                                return False
                        return True

                    while continue_flag():
                        await uasyncio.sleep(1)
                        now = utime.time()
                        current = self._power_monitor.current(
                        ) if self._power_monitor else None
                        if current:
                            self.log_current(current)
                        expired += now - prev_time
                        prev_time = now
                        if current and current > self._reverse_threshold:
                            await self.engine_reverse(True)
                            await uasyncio.sleep(self._reverse_duration)
                            expired -= self._reverse_duration + 2 * self._reverse_delay
                            retries += 1
                            await self.engine_reverse(False)
                    self.off(source=timer)
                if timer.time_on > time:
                    break
            manage_memory()
            await uasyncio.sleep(60 - machine.RTC().now()[6])
Esempio n. 6
0
def load_srv_json(file, srv_url=None):
    global HTTP_CLIENT
    if not srv_url:
        srv_url = updates_url()
    file_url = srv_url + file + '.json'
    try:
        if not HTTP_CLIENT:
            HTTP_CLIENT = HttpClient()
        return HTTP_CLIENT.get_json(file_url)
    except Exception as exc:
        LOG.exc(exc, 'Error loading server data: %s' % file)
        return None
    finally:
        manage_memory()
Esempio n. 7
0
    async def read(self, once=False):

        while True:
            for sensor_device in self.sensor_devices:
                if sensor_device.sensor_type == 'ds18x20':
                    sensor_device.convert()
            await uasyncio.sleep_ms(self._sleep)
            for sensor_device in self.sensor_devices:
                sensor_device.read()
            if self.switches:
                self.adjust_switches()
            manage_memory()
            if once:
                break
 async def srv_post(self, url, data, retry=False):
     if self.busy:
         return False
     data['device_id'] = self.id['id']
     data['token'] = self.id['token']
     manage_memory()
     machine.resetWDT()
     result = await self._http.post(self.server_uri + url, data)
     if retry:
         while not result:
             machine.resetWDT()
             result = await self._http.post(self.server_uri + url, data)
     machine.resetWDT()
     manage_memory()
     return result
Esempio n. 9
0
 async def adjust_switch(self, once=False):
     while True:
         now_tuple = machine.RTC().now()
         now = time_tuple_to_seconds(now_tuple, seconds=True)
         next_time_on = None
         if self._schedule_params:
             day = self.device.schedule.current_day()
             if day:
                 limits = [
                     day[idx] if idx and day[idx] else None
                     for idx in self._schedule_params_idx
                 ]
                 if limits[0] and ((limits[0] <= now and not limits[1]) or
                                   (limits[0] <= now < limits[1]) or
                                   (limits[0] < limits[1] <= now)):
                     self.set_gate_state(1)
                 if limits[1] and ((limits[1] <= now and not limits[0]) or
                                   (limits[1] <= now < limits[0]) or
                                   (limits[1] < limits[0] <= now)):
                     self.set_gate_state(0)
         else:
             if now == 0:
                 self.init_timers()
             passed_timers = [
                 timer for timer in self.timers if timer.time_on <= now
             ]
             if not passed_timers and self.timers:
                 passed_timers = [self.timers[-1]]
             if passed_timers:
                 last_timer = passed_timers[-1]
                 await self.set_gate_state(1 if last_timer.duration ==
                                           0 else 0)
                 next_timers = [
                     timer for timer in self.timers if timer.time_on > now
                 ]
                 if next_timers and last_timer.time_on < next_timers[
                         0].time_on < last_timer.time_on + 60:
                     next_time_on = next_timers[
                         0].time_on - last_timer.time_on
         if once:
             break
         manage_memory()
         if next_time_on:
             await uasyncio.sleep(next_time_on)
         else:
             await uasyncio.sleep(60 - machine.RTC().now()[5])
Esempio n. 10
0
 def on(self, value=True, source='manual', manual=False):
     if manual:
         source = 'manual'
     if value:
         self._active[source] = True
     else:
         if source in self._active:
             del self._active[source]
     if self.state != bool(self._active):
         if self.state:
             self.reverse = False
         self.device.busy = self._active
         RelaySwitchController.on(self, self._active, source == 'manual')
     if 'manual' in self._active and len(
             self._active) == 1 and self._power_monitor:
         uasyncio.get_event_loop().create_task(self.check_current())
     LOG.debug('Feeder state: %s' % self.state)
     manage_memory()
Esempio n. 11
0
def perform_software_update():
    global HTTP_CLIENT
    if not HTTP_CLIENT:
        HTTP_CLIENT = HttpClient()
    machine.WDT()
    manage_memory()
    version_data = load_version()
    device_type = get_device_type()
    srv_url = updates_url()
    srv_index = load_srv_json('index', srv_url=srv_url)
    machine.resetWDT()
    srv_versions = load_srv_json('devices', srv_url=srv_url)
    machine.resetWDT()
    if srv_index:
        for path, entry in srv_index.items():
            if 'devices_types' in entry and 'base' not in entry[
                    'devices_types'] and device_type not in entry[
                        'devices_types']:
                continue
            if path in version_data['files'] and version_data['files'][
                    path] == entry['hash']:
                continue
            local_path = entry['path'] if 'path' in entry else path
            print(local_path)
            ensure_file_path(local_path)
            file_url = srv_url + 'software/' + path
            print(file_url)
            while version_data['files'].get(path) != entry['hash']:
                if HTTP_CLIENT.get_to_file(file_url, 'file_buf'):
                    try:
                        uos.remove(local_path)
                    except OSError:
                        pass
                    uos.rename('file_buf', local_path)
                    if version_data['hash']:
                        version_data['hash'] = None
                    version_data['files'][path] = entry['hash']
                    save_version(version_data)
                    print('complete')
        machine.resetWDT()
        version_data['hash'] = srv_versions[device_type]
        version_data['update'] = False
        save_version(version_data)
    machine.reset()
Esempio n. 12
0
 async def post_log(self):
     while True:
         await uasyncio.sleep(59)
         try:
             if self.log_queue and not self.status['srv_req_pending']:
                 while self.log_queue:
                     entries_count = 10 if len(
                         self.log_queue) > 10 else len(self.log_queue)
                     entries = self.log_queue[:entries_count]
                     rsp = await self.srv_post('devices_log/post',
                                               {'entries': entries})
                     if rsp:
                         self.log_queue = self.log_queue[
                             entries_count:] if entries_count < len(
                                 self.log_queue) else []
                     else:
                         break
         except Exception as exc:
             LOG.exc(exc, 'Server log post error')
         manage_memory()
Esempio n. 13
0
 async def check_updates(self, once=False):
     while True:
         deepsleep = bool(self.deepsleep())
         timezone = self.settings.get('timezone')
         try:
             data = {
                 'schedule': {
                     'hash': self.schedule.hash,
                     'start': self.schedule.start
                 },
                 'props': self.settings
             }
             updates = await self.srv_post('device_updates',
                                           data,
                                           retry=once)
             if updates:
                 if updates.get('schedule'):
                     self.schedule.update(updates['schedule'])
                 if updates.get('props'):
                     self.settings = updates['props']
                     self.save_settings()
                     for ctrl in self.modules.values():
                         if ctrl:
                             ctrl.update_settings()
                 if deepsleep != bool(self.deepsleep()):
                     machine.reset()
                 if timezone != self.settings.get('timezone'):
                     self.ntp_sync()
                 if 'mode' in self.settings and self.mode != self.settings[
                         'mode']:
                     machine.reset()
         except Exception as exc:
             LOG.exc(exc, 'Server updates check error')
         manage_memory()
         if once:
             break
         await uasyncio.sleep(30)
Esempio n. 14
0
async def get_index(req, rsp):
    await APP.sendfile(rsp,
                       'html/index.html',
                       content_type="text/html; charset=utf-8")
    manage_memory()
Esempio n. 15
0
async def send_json(rsp, data):
    await picoweb.start_response(rsp, 'application/json', "200",
                                 {'cache-control': 'no-store'})
    await rsp.awrite(ujson.dumps(data).encode('UTF-8'))
    manage_memory()
Esempio n. 16
0
    machine.resetWDT()


LOOP.create_task(wdt_feed())
machine.WDT(True)

NETWORK_CONTROLLER = NetworkController()

if NETWORK_CONTROLLER.online():
    software_version = load_json('version.json')
    if software_version and software_version['update']:
        from software_update import perform_software_update
        perform_software_update()
        machine.reset()

manage_memory()

DEVICE = LenferDevice(NETWORK_CONTROLLER)
manage_memory()

import lib.picoweb as picoweb
APP = picoweb.WebApp(__name__)


async def send_json(rsp, data):
    await picoweb.start_response(rsp, 'application/json', "200",
                                 {'cache-control': 'no-store'})
    await rsp.awrite(ujson.dumps(data).encode('UTF-8'))
    manage_memory()

Esempio n. 17
0
    def __init__(self, network_controller):
        LOG.info("LenferDevice init")
        self._schedule = None
        self._network = network_controller
        self.mode = None
        self.status = {
            "wlan": None,
            "factory_reset": False,
            "wlan_switch": False,
            "ssid_failure": False,
            "ssid_delay": False,
            "srv_req_pending": False
        }
        self.log_queue = []
        self.busy = False
        self._conf = load_json('conf.json')
        self.settings = load_json('settings.json')
        self._http = HttpClient()
        if not self.settings:
            self.load_def_settings()
        if self.settings.get('mode'):
            self.mode = self.settings['mode']

        if self._conf.get('wlan_switch'):
            self._wlan_switch_button = Pin(self._conf['wlan_switch'],
                                           Pin.IN,
                                           Pin.PULL_UP,
                                           handler=self.wlan_switch_irq,
                                           trigger=Pin.IRQ_FALLING)

        if self._conf.get('factory_reset'):
            self._factory_reset_button = Pin(self._conf['factory_reset'],
                                             Pin.IN,
                                             handler=self.factory_reset_irq,
                                             trigger=Pin.IRQ_FALLING
                                             | Pin.IRQ_RISING)

        self.modules = {}
        self.i2c = [
            I2C(scl=Pin(i2c_conf['scl']), sda=Pin(i2c_conf['sda']))
            for i2c_conf in self._conf['i2c']
        ]
        LOG.info('I2C init')

        self.leds = {
            led: Pin(pin_no, Pin.OUT)
            for led, pin_no in self._conf['leds'].items()
        }
        self.id = load_json('id.json')
        if 'debug' in self.id and self.id['debug']:
            self.server_uri = SERVER_URI_DEV
        else:
            self.server_uri = SERVER_URI
        for led in self.leds.values():
            led.value(0)

        self.schedule = Schedule()
        manage_memory()
        machine.resetWDT()

        if 'rtc' in self._conf['modules'] and self.module_enabled(
                self._conf['modules']['rtc']):
            try:
                from timers import RtcController
                self.modules['rtc'] = RtcController(
                    self, self._conf['modules']['rtc'])
                self.modules['rtc'].get_time(set_rtc=True)
                LOG.info('RTC init')

            except Exception as exc:
                LOG.exc(exc, 'RTC initialization error')
            machine.resetWDT()
            manage_memory()
        if 'climate' in self._conf['modules'] and self.module_enabled(
                self._conf['modules']['climate']):
            try:
                from climate import ClimateController
                self.modules['climate'] = ClimateController(
                    self, self._conf['modules']['climate'])
                LOG.info('ClimateController init')

            except Exception as exc:
                LOG.exc(exc, 'Climate initialization error')
                if self._conf['modules']['climate'].get('obligatory'):
                    LOG.error(
                        'Obligatory module initialization fail -- machine reset'
                    )
                    machine.reset()
            machine.resetWDT()
            manage_memory()
        if 'power_monitor' in self._conf['modules'] and self.module_enabled(
                self._conf['modules']['power_monitor']):
            try:
                from power_monitor_controller import PowerMonitor
                self.modules['power_monitor'] = PowerMonitor(
                    self, self._conf['modules']['power_monitor'])
                LOG.info('PowerMonitor init')

            except Exception as exc:
                LOG.exc(exc, 'PowerMonitor initialization error')
                if self._conf['modules']['power_monitor'].get('obligatory'):
                    LOG.error(
                        'Obligatory module initialization fail -- machine reset'
                    )
                    machine.reset()
            machine.resetWDT()
            manage_memory()

        if 'feeder' in self._conf['modules'] and self.module_enabled(
                self._conf['modules']['feeder']):
            try:
                from feeder import FeederController
                self.modules['feeder'] = FeederController(
                    self, self._conf['modules']['feeder'])
                LOG.info('Feeder init')
            except Exception as exc:
                LOG.exc(exc, 'Feeder initialization error')
            machine.resetWDT()
            manage_memory()

        if 'gate' in self._conf['modules'] and self.module_enabled(
                self._conf['modules']['gate']):
            try:
                from gate_controller import GateController
                self.modules['gate'] = GateController(
                    self, self._conf['modules']['gate'])
                LOG.info('Gate init')
            except Exception as exc:
                LOG.exc(exc, 'Gate initialization error')
            machine.resetWDT()
            manage_memory()

        if 'relay_switch' in self._conf['modules'] and self.module_enabled(
                self._conf['modules']['relay_switch']):
            try:
                from relay_switch import RelaySwitchController
                self.modules['relay_switch'] = RelaySwitchController(
                    self, self._conf['modules']['relay_switch'])
                LOG.info('Relay init')
            except Exception as exc:
                LOG.exc(exc, 'RelaySwitch initialization error')
            machine.resetWDT()
            manage_memory()

        LOG.info(self.modules)
Esempio n. 18
0
    def adjust_switches(self):
        state = {}
        schedule_day = self.device.schedule.current_day()
        for param in self.sensors_roles:
            state[param] = {
                'value': [
                    self.data[sensor_idx]
                    for sensor_idx in self.sensors_roles[param]
                    if self.data[sensor_idx] != None
                ],
                'limits': []
            }
            if state[param]['value']:
                param_value, param_delta = None, None
                if schedule_day:
                    param_idx = self.device.schedule.param_idx(param)
                    if param_idx != -1:
                        param_value = schedule_day[param_idx]
                        param_delta = self.device.schedule.params['delta'][
                            param_idx]
                if param_value == None or param_delta == None:
                    if self.device.settings.get(param):
                        param_value, param_delta = self.device.settings[param]
                if param_value != None and param_delta != None:
                    state[param]['limits'] = [
                        param_value - param_delta,
                        param_value + param_delta,
                    ]

        if state.get('temperature') and state['temperature']['value']:
            if self.switches['heat']['enabled'] and state['temperature'][
                    'limits']:
                if state['temperature']['value'][0] < state['temperature'][
                        'limits'][0]:
                    if not self.switches['heat']['pin'].value():
                        self.switches['heat']['pin'].value(1)
                        LOG.info('Heat on')
                else:
                    if self.switches['heat']['pin'].value():
                        self.switches['heat']['pin'].value(0)
                        LOG.info('Heat off')
            if self.switches['vent_mix']['enabled']:
                if len(state['temperature']['value']) > 1:
                    if state['temperature']['value'][0] > state['temperature']['value'][1] + 3 or\
                        state['temperature']['value'][0] < state['temperature']['value'][1] - 3:
                        if not self.switches['vent_mix']['pin'].value():
                            self.switches['vent_mix']['pin'].value(1)
                            LOG.info('Mix on')
                    elif state['temperature']['value'][0] < state['temperature']['value'][1] + 1 and\
                        state['temperature']['value'][0] > state['temperature']['value'][1] - 1:
                        if self.switches['vent_mix']['pin'].value():
                            self.switches['vent_mix']['pin'].value(0)
                            LOG.info('Mix off')
        if self.switches['vent_mix']['enabled']:
            if not state.get('temperature') or len(
                    state['temperature']['value']) < 2:
                if self.switches['vent_mix']['pin'].value():
                    self.switches['vent_mix']['pin'].value(0)
                    LOG.info('Mix off')
        if self.switches['vent_out']['enabled']:
            if (state.get('humidity') and state['humidity']['value'] and state['humidity']['limits'] and\
                    state['humidity']['value'][0] > state['humidity']['limits'][1]) or\
                (state.get('temperature') and state['temperature']['value'] and state['temperature']['limits'] and\
                    state['temperature']['value'][0] > state['temperature']['limits'][1]) or\
                (state.get('co2') and state['co2']['value'][0] > ClimateController.CO2_THRESHOLD):
                if not self.switches['vent_out']['pin'].value():
                    self.switches['vent_out']['pin'].value(1)
                    LOG.info('Out on')
            else:
                if self.switches['vent_out']['pin'].value():
                    self.switches['vent_out']['pin'].value(0)
                    LOG.info('Out off')
        if self.switches['humid']['enabled']:
            if state.get('humidity') and state['humidity']['value'] and state['humidity']['limits'] and\
                state['humidity']['value'][0] < state['humidity']['limits'][0]:
                if not self.switches['humid']['pin'].value():
                    self.switches['humid']['pin'].value(1)
                    LOG.info('Humid on')
            else:
                if self.switches['humid']['pin'].value():
                    self.switches['humid']['pin'].value(0)
                    LOG.info('Humid off')
        if self.switches['air_con']['enabled']:
            if state.get('temperature') and state['temperature']['value'] and state['temperature']['limits'] and\
                    state['temperature']['value'][0] > state['temperature']['limits'][1] + 3:
                if not self.switches['air_con']['pin'].value():
                    self.switches['air_con']['pin'].value(1)
                    LOG.info('Air con on')
                    if self.switches['vent_out']['enabled'] and self.switches['vent_out']['pin'].value()\
                        and (not state.get('co2') or not state['co2']['value'] or state['co2']['value'][0] < ClimateController.CO2_THRESHOLD):
                        self.switches['vent_out']['pin'].value(0)
            else:
                if self.switches['air_con']['pin'].value():
                    self.switches['air_con']['pin'].value(0)
                    LOG.info('Air con off')

        manage_memory()