예제 #1
0
파일: database.py 프로젝트: eigenein/my-iot
def save_event(db: Connection, event: Event) -> None:
    with db:
        if event.unit.is_stored:
            db[ACTUAL_KEY][event.channel] = event.dict()
        if event.unit.is_logged:
            db[f'log:{event.channel}'][timestamp_key(
                event.timestamp)] = event.dict(include=EVENT_INCLUDE)
예제 #2
0
파일: database.py 프로젝트: eigenein/my-iot
def get_log(db: Connection, channel: str, period: timedelta) -> List[Event]:
    """
    Gets the channel log within the specified period until now.
    """
    return [
        Event(**event)
        for event in db[f'log:{channel}'][timestamp_key(datetime.now() -
                                                        period):]
    ]
예제 #3
0
 async def events(self):
     for i in count(start=1):
         logger.trace('Sleeping for {interval} seconds…',
                      interval=self.interval)
         await sleep(self.interval)
         yield Event(channel=f'clock:{self.sub_channel}',
                     value=i,
                     title=self.title,
                     unit=Unit.TEXT)
예제 #4
0
 def yield_events(self, feed: Any) -> Iterable[Event]:
     if feed['actual']['sunrise']:
         sunrise = parse_datetime(feed['actual']['sunrise'])
         yield Event(
             channel='buienradar:sunrise',
             value=sunrise,
             unit=Unit.DATETIME,
             title='Sunrise',
         )
     else:
         logger.warning('Sunrise time is missing.')
         sunrise = None
     if feed['actual']['sunset']:
         sunset = parse_datetime(feed['actual']['sunset'])
         yield Event(
             channel='buienradar:sunset',
             value=sunset,
             unit=Unit.DATETIME,
             title='Sunset',
         )
     else:
         logger.warning('Sunset time is missing.')
         sunset = None
     if sunset and sunrise:
         yield Event(
             channel='buienradar:day_length',
             value=(sunset - sunrise),
             unit=Unit.TIMEDELTA,
             title='Day Length',
         )
     try:
         measurement = self.find_measurement(feed)
     except KeyError as e:
         logger.error('Station ID {} is not found.', e)
         return
     timestamp = parse_datetime(measurement['timestamp'])
     for key, channel, unit, title in channels:
         yield Event(
             channel=f'buienradar:{self.station_id}:{channel}',
             value=measurement[key],
             unit=unit,
             timestamp=timestamp,
             title=f'{measurement["stationname"]} {title}',
         )
예제 #5
0
def yield_devices_events(devices: dict, prefix: str,
                         keys: List[Tuple[str, Unit, str]]) -> Iterable[Event]:
    for id_, device in devices.items():
        for key, unit, title in keys:
            yield Event(
                channel=f'{prefix}:{id_}:{key}',
                value=device[key],
                unit=unit,
                title=f'{device.get("name_long") or device["name"]} {title}',
            )
예제 #6
0
파일: file_.py 프로젝트: eigenein/my-iot
 async def events(self):
     try:
         yield Event(
             channel=f'file:{self.sub_channel}',
             value=self.preprocess_value(self.path.read_text()),
             unit=self.unit,
             title=self.title,
         )
     except IOError as e:
         logger.error('I/O error in {channel}:', channel=self)
         logger.error('{e}', e=e)
     logger.debug('Next reading in {interval} seconds.',
                  interval=self.interval)
     await sleep(self.interval)
예제 #7
0
파일: __main__.py 프로젝트: eigenein/my-iot
async def on_startup(app: Application):
    """
    Set up the web application.
    """
    context: Context = app['context']
    await context.on_event(
        Event(
            value=pkg_resources.get_distribution('my_iot').version,
            channel='my_iot:version',
            unit=Unit.TEXT,
            title='My IoT version',
        ))
    # noinspection PyAsyncCall
    create_task(context.run_services())
예제 #8
0
파일: context.py 프로젝트: eigenein/my-iot
 async def on_event(self, event: Event):
     """
     Handle the single event.
     """
     logger.info('{key} = {value!r}', key=event.channel, value=event.value)
     previous = self.db[ACTUAL_KEY].get(event.channel)
     await run_in_executor(save_event, self.db, event)
     previous = Event(**previous) if previous is not None else None
     # noinspection PyAsyncCall
     create_task(
         router.on_event(
             event=event,
             previous=previous,
             actual=(await run_in_executor(get_actual, self.db)),
             session=self.session,
         ))
예제 #9
0
def yield_events(event: MessageEvent) -> Iterable[Event]:
    data: dict = loads(event.data)['data']
    devices: dict = data['devices']

    yield from yield_devices_events(data['structures'], 'nest:structure', [
        ('away', Unit.ENUM, 'Away'),
        ('wwn_security_state', Unit.ENUM, 'Security State'),
    ])
    yield from yield_devices_events(devices['cameras'], 'nest:camera', [
        ('is_streaming', Unit.BOOLEAN, 'Streaming'),
        ('is_online', Unit.BOOLEAN, 'Online'),
        ('snapshot_url', Unit.IMAGE_URL, 'Snapshot'),
    ])
    yield from yield_devices_events(
        devices['thermostats'], 'nest:thermostat', [
            ('ambient_temperature_c', Unit.CELSIUS, 'Ambient Temperature'),
            ('humidity', Unit.RH, 'Humidity'),
            ('is_online', Unit.BOOLEAN, 'Online'),
            ('hvac_state', Unit.ENUM, 'HVAC'),
            ('target_temperature_c', Unit.CELSIUS, 'Target Temperature'),
        ])
    yield from yield_devices_events(devices['smoke_co_alarms'],
                                    'nest:smoke_co_alarm', [
                                        ('is_online', Unit.BOOLEAN, 'Online'),
                                    ])

    for camera_id, camera in devices['cameras'].items():
        last_event = camera.get('last_event')
        if last_event:
            yield Event(
                channel=f'nest:camera:{camera_id}:last_animated_image_url',
                value=last_event['animated_image_url'],
                unit=Unit.IMAGE_URL,
                timestamp=datetime.strptime(last_event['start_time'],
                                            timestamp_format),
                title=f'{camera["name_long"]} Last Event',
            )
예제 #10
0
async def get_channel(request: web.Request) -> dict:
    context: Context = request.app['context']
    channel: str = request.match_info['channel']
    try:
        raw_event: Dict[Any, Any] = context.db[ACTUAL_KEY][channel]
    except KeyError:
        raise HTTPNotFound(text='Channel is not found.')
    event = Event(**raw_event)
    try:
        period = timedelta(seconds=abs(int(request.query.get('period'))))
    except (TypeError, ValueError):
        period = DEFAULT_PERIOD
    events = await run_in_executor(get_log, context.db, channel, period)
    chart = None
    if events:
        if event.unit.is_float:
            chart = await run_in_executor(make_float_chart, events)
    return {
        'chart': chart,
        'event': event,
        'has_events': bool(events),
        'raw_event': raw_event,
        'request': request,
    }
예제 #11
0
파일: database.py 프로젝트: eigenein/my-iot
def get_actual(db: Connection) -> Mapping[str, Event]:
    """
    Get actual channel values.
    """
    return {key: Event(**value) for key, value in db[ACTUAL_KEY].items()}