diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2022-06-14 02:44:43 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2022-06-14 22:56:46 +0300 |
commit | e3d3d6b76010a6dd5c417f017339bec17fb07887 (patch) | |
tree | 42cb6194504ae863db2bf7d21ef9e2acd41d0fd2 /src/camera_node.py | |
parent | 600fdf99ffd893857c9cdb9e68140766a963bd17 (diff) |
media: refactor sound_node, introduce camera_node
Diffstat (limited to 'src/camera_node.py')
-rwxr-xr-x | src/camera_node.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/camera_node.py b/src/camera_node.py new file mode 100755 index 0000000..206361a --- /dev/null +++ b/src/camera_node.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +import asyncio +import time + +from home.config import config +from home.media import MediaNodeServer, CameraRecordStorage, CameraRecorder +from home.camera import CameraType, esp32 +from home.util import parse_addr, Addr +from home import http + + +# Implements HTTP API for a camera. +# --------------------------------- + +class ESP32CameraNodeServer(MediaNodeServer): + def __init__(self, web_addr: Addr, *args, **kwargs): + super().__init__(*args, **kwargs) + self.last_settings_sync = 0 + + self.web = esp32.WebClient(web_addr) + self.get('/capture/', self.capture) + + async def capture(self, req: http.Request): + await self.sync_settings_if_needed() + + try: + with_flash = int(req.query['with_flash']) + except KeyError: + with_flash = 0 + + if with_flash: + await self.web.setflash(True) + await asyncio.sleep(0.2) + + bytes = (await self.web.capture()).read() + + if with_flash: + await self.web.setflash(False) + + res = http.StreamResponse() + res.content_type = 'image/jpeg' + res.content_length = len(bytes) + + await res.prepare(req) + await res.write(bytes) + await res.write_eof() + + return res + + async def do_record(self, request: http.Request): + await self.sync_settings_if_needed() + + # sync settings + return super().do_record(request) + + async def sync_settings_if_needed(self): + if self.last_settings_sync != 0 and time.time() - self.last_settings_sync < 300: + return + changed = await self.web.syncsettings(config['camera']['settings']) + if changed: + self.logger.debug('sync_settings_if_needed: some settings were changed, sleeping for 0.4 sec') + await asyncio.sleep(0.4) + self.last_settings_sync = time.time() + + +if __name__ == '__main__': + config.load('camera_node') + + storage = CameraRecordStorage(config['node']['storage']) + + recorder_kwargs = {} + camera_type = CameraType(config['camera']['type']) + if camera_type == CameraType.ESP32: + recorder_kwargs['stream_addr'] = parse_addr(config['camera']['stream_addr']) + else: + raise RuntimeError(f'unsupported camera type {camera_type}') + + recorder = CameraRecorder(storage=storage, + camera_type=camera_type, + **recorder_kwargs) + recorder.start_thread() + + server = ESP32CameraNodeServer( + recorder=recorder, + storage=storage, + web_addr=parse_addr(config['camera']['web_addr']), + addr=parse_addr(config['node']['listen'])) + server.run() |