summaryrefslogtreecommitdiff
path: root/src/camera_node.py
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2022-06-14 02:44:43 +0300
committerEvgeny Zinoviev <me@ch1p.io>2022-06-14 22:56:46 +0300
commite3d3d6b76010a6dd5c417f017339bec17fb07887 (patch)
tree42cb6194504ae863db2bf7d21ef9e2acd41d0fd2 /src/camera_node.py
parent600fdf99ffd893857c9cdb9e68140766a963bd17 (diff)
media: refactor sound_node, introduce camera_node
Diffstat (limited to 'src/camera_node.py')
-rwxr-xr-xsrc/camera_node.py88
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()