Beispiel #1
0
    def __init__(self):
        global DISPLAY_TYPE

        self._current_program = -1
        self._is_backlit = True
        self._backlight_change = datetime.datetime(9999, 12, 31)
        self._command = ''
        self._message_timeout = datetime.datetime(9999, 12, 31)
        self.line = [''] * LCD_ROWS
        self.old_line = [''] * LCD_ROWS
        self.position = [-LCD_LINE_DELAY] * LCD_ROWS

        try:
            if DISPLAY_TYPE == GPIO_CharLCD:
                # initialize display
                self.lcd = RPiGPIO_CharLCD(LCD_RS, LCD_EN, LCD_D4, LCD_D5,
                                           LCD_D6, LCD_D7, LCD_COLUMNS,
                                           LCD_ROWS, LCD_BACKLIGHT)
            elif DISPLAY_TYPE == I2C_LCD:
                # initialize display
                self.lcd = I2C_LCD_driver.lcd(I2C_ADDRESS, I2C_BUS)
            # load symbol font data
            self._load_charset()
        except KeyboardInterrupt:
            raise
        except Exception:
            log_stderr(traceback.format_exc())
            log_stderr('ERR: LCD init failed - disabling display')
            DISPLAY_TYPE = NONE
Beispiel #2
0
def get_temperature():
    global temp
    global temp_avg_accu, temp_avg_counter, temp_avg_sum
    global log_temp_avg_accu, log_temp_avg_counter, log_temp_avg_sum
    # get temperature (moving average)
    # temperature is sampled n times ('get_temp'): each read is accumulated
    # in temp_avg_accu, with progressive weights (temp * n),
    # so more recent reads have priority.
    # At 'update_io' average temp is logged.
    if config.TEST_MODE > 0:
        temp += -10 * TEST_DELTA_EXT_INT_COEFF
        if io_status.heating_status == 'on' or \
                io_status.heating_status == 'warming':
            temp += TEST_DELTA_THERMO_ON_TEMP_C
            # sensors delay test
            time.sleep(random.uniform(.0, .2))
    else:
        temp = sensor.read_temp()
    # skip wrong reads (null or > 50°C)
    if not temp or temp > 50.0:
        log_stderr('Temp sensor error: received {}'.format(temp))
    else:
        # accumulate temperature read
        temp_avg_counter += 1 + (.5 / task_every_secs['update_io'] /
                                 task_every_secs['get_temp'])
        temp_avg_sum += temp_avg_counter
        temp_avg_accu += temp * temp_avg_counter
        log_temp_avg_counter = 1
        log_temp_avg_sum += log_temp_avg_counter
        log_temp_avg_accu += temp * log_temp_avg_counter
        print('Req: {:.2f}° - Int: {:.2f}° - Thermo: {}'.format(
            io_status.req_temp_c, temp, io_status.heating_status))
Beispiel #3
0
def aphorism():
    aphorism = sensor.get_aphorism()
    try:
        if aphorism:
            io_status.aphorism_text = aphorism['quoteText'].strip()
            io_status.aphorism_author = aphorism['quoteAuthor'].strip()
        else:
            # just show a small mark on app
            if (io_status.aphorism_text and
                    ' (*)' not in io_status.aphorism_text):
                io_status.aphorism_text += ' (*)'
    except Exception:
        io_status.aphorism_text = 'Error fetching aphorism'
        log_stderr(traceback.format_exc())
        log_data('APHOEXC: {}'.format(traceback.format_exc()))
Beispiel #4
0
 def hompi_slaves_forward_command(self, hompi_slaves, command):
     for slave_id, slave_data in hompi_slaves.items():
         if slave_id != config.HOMPI_ID:
             try:
                 command_json = json.dumps({'data': command})
                 request.urlopen(
                     '{}/hompi/_send_command/{}?api_key={}'.format(
                         slave_data['address'], request.quote(command_json),
                         API_KEY),
                     timeout=2)
                 print('Forwarded COMMAND: {} to: {}'.format(
                     command, slave_id))
             except request.URLError:
                 print('WARNING: {} server not available.'.format(slave_id))
             except Exception:
                 log_stderr(traceback.format_exc())
Beispiel #5
0
    def __init__(self):
        global AMBIENT_ENABLED

        self._poweroff_time = datetime.datetime(9999, 12, 31)
        self._current_ambient_command = ''
        self._set_current_ambient_color('000000')

        try:
            if AMBIENT_ENABLED:
                self.cleanup()
        except KeyboardInterrupt:
            raise
        except Exception:
            log_stderr(traceback.format_exc())
            log_stderr(
                '*AMBIENT ERR* : LED strip init failed - disabling AMBIENT')
            AMBIENT_ENABLED = False
Beispiel #6
0
 def get_meteo(self):
     meteo = None
     try:
         meteo = json.load(
             reader(
                 request.urlopen(self.METEO_URL.replace(
                     '[place]', config.PLACE),
                                 timeout=5)))
         print((
             '{} - Weather: {} - Temp.: {}° - Humidity: {}% Pressure: {} ' +
             'mbar - Wind: {} m/s').format(meteo['name'],
                                           meteo['weather'][0]['main'],
                                           meteo['main']['temp'],
                                           meteo['main']['humidity'],
                                           meteo['main']['pressure'],
                                           meteo['wind']['speed']))
     except request.URLError:
         print('WARNING: meteo not available.')
     except Exception:
         log_stderr(traceback.format_exc())
     finally:
         return meteo
Beispiel #7
0
def log_data(event):
    try:
        description = ''
        if not event:
            event = 'null'
        else:
            if event == '.':
                # log all temperatures
                for id, data in io_status.hompi_slaves.items():
                    description += str(data['int_temp_c']) + ';'
            event = "'{}'".format(event.replace('\'', '\'\''))

        if not description:
            if config.VERBOSE_LOG:
                description = "'{}'".format(
                    io_status.get_output().replace('\'', '\'\''))
            else:
                description = 'null'
        else:
            # remove last ; and add quotes
            description = "'{}'".format(description[:-1])

        if not config.MODULE_DB_LOG:
            return

        dbmgr = db.DatabaseManager()
        dbmgr.query("""
            INSERT INTO gm_log
            (datetime, int_temp_c, ext_temp_c, req_temp_c, event, description)
            VALUES (strftime('%s','now'), {:f}, {:f}, {:f}, {}, {})
            """.format(io_status.int_temp_c, io_status.ext_temp_c,
                       io_status.req_temp_c, event, description))
        print('Logged data: {}'.format(event))
    except (KeyboardInterrupt, SystemExit):
        raise
    except Exception:
        log_stderr('log_data error: {}'.format(traceback.format_exc()))
        time.sleep(1)
Beispiel #8
0
def meteo():
    meteo = sensor.get_meteo()
    try:
        if meteo:
            io_status.place = io_status.weather = ''
            io_status.ext_temp_c = io_status.humidity = 0
            io_status.pressure = io_status.wind = 0.0

            io_status.place = meteo['name']
            if len(meteo['weather']) > 0:
                io_status.weather = meteo['weather'][0]['main']
            io_status.ext_temp_c = meteo['main']['temp']
            io_status.humidity = meteo['main']['humidity']
            io_status.pressure = meteo['main']['pressure']
            io_status.wind = meteo['wind']['speed']
        else:
            # occurs too often: just show a small mark on app
            if (' (*)' not in io_status.place):
                io_status.place += ' (*)'
    except (KeyError, ValueError):
        io_status.place = 'Error fetching meteo'
        log_stderr(traceback.format_exc())
        log_data('METEOEXC: {}'.format(traceback.format_exc()))
Beispiel #9
0
def main():
    global sig_command, refreshing, is_status_changed, lcd
    global initial_time
    global temp, temp_avg_accu, temp_avg_counter, temp_avg_sum
    global log_temp_avg_accu, log_temp_avg_counter, log_temp_avg_sum

    last_update_min = -1

    # will sys.exit(-1) if other instance is running
    singleton.SingleInstance()

    # first initializations
    init()

    # main loop
    log_data('start')
    show_message('HOMPI', 'HOMPI START')

    while True:
        try:
            # save cycle start time
            cycle_start_time = datetime.datetime.now()
            secs_elapsed = round(
                (cycle_start_time - initial_time).total_seconds())
            # time in the day
            current_time = datetime.datetime.today().hour * 100 + \
                datetime.datetime.today().minute

            #  refresh at end time (do once per minute)
            if (io_status.req_end_time == current_time and
                    last_update_min != datetime.datetime.today().minute):
                last_update_min = datetime.datetime.today().minute
                refreshing = True

            # OPERATIONS NOT DONE ON REFRESH - START
            # update hompiS
            if secs_elapsed >= task_at_secs['hompi_slaves_refresh']:
                sensor.hompi_slaves_refresh(io_status.hompi_slaves)

            # update I/O: meteo
            if secs_elapsed >= task_at_secs['get_meteo'] \
                    and config.MODULE_METEO:
                meteo()

            # aphorism
            if secs_elapsed >= task_at_secs['get_aphorism'] \
                    and config.MODULE_APHORISM:
                aphorism()

            # re-sync things
            if secs_elapsed >= task_at_secs['refresh']:
                # restart LCD
                lcd = dashboard.Dashboard()
                # ambient color
                if config.MODULE_AMBIENT:
                    io_status.current_ambient_color = ambient.ambient_refresh()
                # temp sensor failure: reset temp sampling
                if config.MODULE_TEMP and temp_avg_sum == 0:
                    temp_avg_accu = temp_avg_counter = 0.0
                    io_status.int_temp_c = 0.0
            # OPERATIONS NOT DONE ON REFRESH - END

            # update I/O (ack occurring here gets ambient control)
            if secs_elapsed >= task_at_secs['update_io'] or refreshing:
                process_input()

            # get temperature
            if (secs_elapsed >= task_at_secs[
                    'get_temp'] or refreshing) and config.MODULE_TEMP:
                get_temperature()

            # update temperature
            if (secs_elapsed >= task_at_secs[
                    'update_temp'] or refreshing):
                # save new temperature (if valid)
                if temp_avg_sum != 0:
                    io_status.int_temp_c = \
                        round(temp_avg_accu / temp_avg_sum, 2)
                # reset temp sampling
                temp_avg_accu = temp_avg_counter = temp_avg_sum = 0

            # refresh program
            if secs_elapsed >= task_at_secs['refresh'] or refreshing:
                refresh_program(current_time)

            # compute status (heating, switches, ...)
            is_status_changed |= compute_status()

            # update I/O: output
            if secs_elapsed >= task_at_secs['update_io'] or \
                    refreshing or is_status_changed:
                update_output()

            # log data (check task_at_mins)
            if (datetime.datetime.now().minute == task_at_mins[
                'log'] or refreshing) \
                    and log_temp_avg_sum > 0:
                io_status.int_temp_c = round(
                    log_temp_avg_accu / log_temp_avg_sum, 2)
                log_temp_avg_accu = log_temp_avg_counter = log_temp_avg_sum = 0
                log_data('refreshing' if refreshing else '.')

            # update LCD message (NOT ON REFRESH)
            if secs_elapsed >= task_at_secs['update_lcd_content']:
                update_lcd_content()

            # status speech
            if is_status_changed and config.MODULE_SPEECH:
                command = config.SPEECH_COMMAND.format(
                    io_status.get_status_text()) + ' &'
                print('status changed: executing {}'.format(command))
                os.system(command)

        except (KeyboardInterrupt, SystemExit):
            # cleanup sensors & LCD
            sensor.cleanup()
            lcd.cleanup()
            ambient.cleanup()
            raise
        except Exception:
            log_stderr(traceback.format_exc())
            log_data('EXC: {}'.format(traceback.format_exc()))
        finally:
            # stop refreshing cycle, reset status change
            refreshing = is_status_changed = False

            # update scheduled tasks (skip any lost task)
            for task in task_every_secs.keys():
                while secs_elapsed >= task_at_secs[task]:
                    task_at_secs[task] += task_every_secs[task]

            for task in task_every_mins.keys():
                if datetime.datetime.now().minute == task_at_mins[task]:
                    task_at_mins[task] += task_every_mins[task]
                    while task_at_mins[task] >= 60:
                        task_at_mins[task] -= 60

            # sync ambient color
            io_status.current_ambient_color = ambient.update()

            try:
                # update lcd screen to 1 sec approx.
                cycle_duration = (datetime.datetime.now() - cycle_start_time)\
                    .total_seconds()
                while cycle_duration < 1:
                    # catch command "interrupt" (jump to new cycle)
                    if sig_command:
                        break
                    frame_duration = lcd.update(io_status)
                    if frame_duration < .25:
                        time.sleep(.25 - frame_duration)
                    cycle_duration += .25

                if sig_command:
                    sig_command = False
                    refreshing = True

            except (KeyboardInterrupt, SystemExit):
                # cleanup sensors & LCD
                sensor.cleanup()
                lcd.cleanup()
                ambient.cleanup()
                raise
            except Exception:
                # LCD I/O error: refresh LCD screen
                log_stderr(traceback.format_exc())
                log_stderr('LCD I/O error: trying to recover..')
                time.sleep(1)
                lcd = dashboard.Dashboard()