diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2023-09-13 09:34:49 +0300 |
---|---|---|
committer | Evgeny Sorokin <me@ch1p.io> | 2024-01-13 00:57:00 +0000 |
commit | 7058d0f5063dc9b065248d0a906cf874788caecf (patch) | |
tree | 26468a5d5a7f8c05804911b3fbf649d952bfd8f1 /bin | |
parent | 57955b596485ecce1ffd4395e23c078358cc5ddd (diff) |
save
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/mqtt_node_util.py | 56 | ||||
-rw-r--r-- | bin/web_kbn.py | 117 |
2 files changed, 161 insertions, 12 deletions
diff --git a/bin/mqtt_node_util.py b/bin/mqtt_node_util.py index cf451fd..5587739 100755 --- a/bin/mqtt_node_util.py +++ b/bin/mqtt_node_util.py @@ -7,12 +7,37 @@ from typing import Optional from argparse import ArgumentParser, ArgumentError from homekit.config import config -from homekit.mqtt import MqttNode, MqttWrapper, get_mqtt_modules -from homekit.mqtt import MqttNodesConfig +from homekit.mqtt import MqttNode, MqttWrapper, get_mqtt_modules, MqttNodesConfig +from homekit.mqtt.module.relay import MqttRelayModule +from homekit.mqtt.module.ota import MqttOtaModule mqtt_node: Optional[MqttNode] = None mqtt: Optional[MqttWrapper] = None +relay_module: Optional[MqttOtaModule] = None +relay_val = None + +ota_module: Optional[MqttRelayModule] = None +ota_val = False + +no_wait = False +stop_loop = False + + +def on_mqtt_connect(): + global stop_loop + + if relay_module: + relay_module.switchpower(relay_val == 1) + + if ota_val: + if not os.path.exists(arg.push_ota): + raise OSError(f'--push-ota: file \"{arg.push_ota}\" does not exists') + ota_module.push_ota(arg.push_ota, 1) + + if no_wait: + stop_loop = True + if __name__ == '__main__': nodes_config = MqttNodesConfig() @@ -23,18 +48,23 @@ if __name__ == '__main__': help='mqtt modules to include') parser.add_argument('--switch-relay', choices=[0, 1], type=int, help='send relay state') - parser.add_argument('--legacy-relay', action='store_true') parser.add_argument('--push-ota', type=str, metavar='OTA_FILENAME', help='push OTA, receives path to firmware.bin') + parser.add_argument('--no-wait', action='store_true', + help='execute command and exit') config.load_app(parser=parser, no_config=True) arg = parser.parse_args() + if arg.no_wait: + no_wait = True + if arg.switch_relay is not None and 'relay' not in arg.modules: raise ArgumentError(None, '--relay is only allowed when \'relay\' module included in --modules') mqtt = MqttWrapper(randomize_client_id=True, client_id='mqtt_node_util') + mqtt.add_connect_callback(on_mqtt_connect) mqtt_node = MqttNode(node_id=arg.node_id, node_secret=nodes_config.get_node(arg.node_id)['password']) @@ -42,27 +72,29 @@ if __name__ == '__main__': # must-have modules ota_module = mqtt_node.load_module('ota') + ota_val = arg.push_ota + mqtt_node.load_module('diagnostics') if arg.modules: for m in arg.modules: kwargs = {} - if m == 'relay' and arg.legacy_relay: + if m == 'relay' and MqttNodesConfig().node_uses_legacy_relay_power_payload(arg.node_id): kwargs['legacy_topics'] = True + if m == 'temphum' and MqttNodesConfig().node_uses_legacy_temphum_data_payload(arg.node_id): + kwargs['legacy_payload'] = True module_instance = mqtt_node.load_module(m, **kwargs) if m == 'relay' and arg.switch_relay is not None: - module_instance.switchpower(arg.switch_relay == 1) + relay_module = module_instance + relay_val = arg.switch_relay try: mqtt.connect_and_loop(loop_forever=False) - - if arg.push_ota: - if not os.path.exists(arg.push_ota): - raise OSError(f'--push-ota: file \"{arg.push_ota}\" does not exists') - ota_module.push_ota(arg.push_ota, 1) - - while True: + while not stop_loop: sleep(0.1) except KeyboardInterrupt: + pass + + finally: mqtt.disconnect() diff --git a/bin/web_kbn.py b/bin/web_kbn.py new file mode 100644 index 0000000..8b4ca6f --- /dev/null +++ b/bin/web_kbn.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +import asyncio +import jinja2 +import aiohttp_jinja2 +import os +import __py_include + +from io import StringIO +from typing import Optional +from homekit.config import config, AppConfigUnit +from homekit.util import homekit_path +from aiohttp import web +from homekit import http +from homekit.modem import ModemsConfig + + +class WebKbnConfig(AppConfigUnit): + NAME = 'web_kbn' + + @classmethod + def schema(cls) -> Optional[dict]: + return { + 'listen_addr': cls._addr_schema(required=True), + 'assets_public_path': {'type': 'string'} + } + + +STATIC_FILES = [ + 'bootstrap.min.css', + 'bootstrap.min.js', + 'polyfills.js', + 'app.js', + 'app.css' +] + + +def get_js_link(file, version) -> str: + if version: + file += f'?version={version}' + return f'<script src="{config.app_config["assets_public_path"]}/{file}" type="text/javascript"></script>' + + +def get_css_link(file, version) -> str: + if version: + file += f'?version={version}' + return f'<link rel="stylesheet" type="text/css" href="{config.app_config["assets_public_path"]}/{file}">' + + +def get_head_static() -> str: + buf = StringIO() + for file in STATIC_FILES: + v = 1 + try: + q_ind = file.index('?') + v = file[q_ind+1:] + file = file[:file.index('?')] + except ValueError: + pass + + if file.endswith('.js'): + buf.write(get_js_link(file, v)) + else: + buf.write(get_css_link(file, v)) + return buf.getvalue() + + +class WebSite(http.HTTPServer): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + aiohttp_jinja2.setup( + self.app, + loader=jinja2.FileSystemLoader(homekit_path('web', 'kbn_templates')) + ) + + self.app.router.add_static('/assets/', path=homekit_path('web', 'kbn_assets')) + + self.get('/main.cgi', self.get_index) + self.get('/modems.cgi', self.get_modems) + + async def render_page(self, + req: http.Request, + template_name: str, + title: Optional[str] = None, + context: Optional[dict] = None): + if context is None: + context = {} + context = { + **context, + 'head_static': get_head_static() + } + if title is not None: + context['title'] = title + response = aiohttp_jinja2.render_template(template_name+'.j2', req, context=context) + return response + + async def get_index(self, req: http.Request): + return await self.render_page(req, 'index', + title="Home web site") + + async def get_modems(self, req: http.Request): + mc = ModemsConfig() + print(mc) + return await self.render_page(req, 'modems', + title='Состояние модемов', + context=dict(modems=ModemsConfig())) + + +if __name__ == '__main__': + config.load_app(WebKbnConfig) + + loop = asyncio.get_event_loop() + # print(config.app_config) + + print(config.app_config['listen_addr'].host) + server = WebSite(config.app_config['listen_addr']) + server.run() |