summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorEvgeny Sorokin <me@ch1p.io>2024-01-16 03:31:55 +0300
committerEvgeny Sorokin <me@ch1p.io>2024-01-16 03:32:07 +0300
commit8a89dd77be03ca8eb9cdc378ba8e912292494fa9 (patch)
treef2d04c1a6ce8b2731febbf6b66f6127057f9477d /bin
parentde56aa3ae916ac0d51e503648fae8f3fa2d97951 (diff)
inverter page
Diffstat (limited to 'bin')
-rw-r--r--bin/web_kbn.py108
1 files changed, 98 insertions, 10 deletions
diff --git a/bin/web_kbn.py b/bin/web_kbn.py
index 113554e..d9d0035 100644
--- a/bin/web_kbn.py
+++ b/bin/web_kbn.py
@@ -3,16 +3,17 @@ import asyncio
import jinja2
import aiohttp_jinja2
import json
-import os
import re
+import inverterd
import __py_include
from io import StringIO
+from aiohttp.web import HTTPFound
from typing import Optional, Union
from homekit.config import config, AppConfigUnit
from homekit.util import homekit_path, filesize_fmt, seconds_to_human_readable_string
from homekit.modem import E3372, ModemsConfig, MacroNetWorkType
-from aiohttp import web
+from homekit.inverter.config import InverterdConfig
from homekit import http
@@ -90,6 +91,69 @@ def get_modem_data(modem_cfg: dict, get_raw=False) -> Union[dict, tuple]:
}
+def get_inverter_client() -> inverterd.Client:
+ cl = inverterd.Client(host=InverterdConfig()['remote_addr'].host)
+ cl.connect()
+ cl.format(inverterd.Format.JSON)
+ return cl
+
+
+def get_inverter_data() -> tuple:
+ cl = get_inverter_client()
+
+ status = json.loads(cl.exec('get-status'))['data']
+ rated = json.loads(cl.exec('get-rated'))['data']
+
+ power_direction = status['battery_power_direction'].lower()
+ power_direction = re.sub('ge$', 'ging', power_direction)
+
+ charging_rate = ''
+ if power_direction == 'charging':
+ charging_rate = ' @ %s %s' % (
+ status['battery_charge_current']['value'],
+ status['battery_charge_current']['unit'])
+ elif power_direction == 'discharging':
+ charging_rate = ' @ %s %s' % (
+ status['battery_discharge_current']['value'],
+ status['battery_discharge_current']['unit'])
+
+ html = '<b>Battery:</b> %s %s' % (
+ status['battery_voltage']['value'],
+ status['battery_voltage']['unit'])
+ html += ' (%s%s, ' % (
+ status['battery_capacity']['value'],
+ status['battery_capacity']['unit'])
+ html += '%s%s)' % (power_direction, charging_rate)
+
+ html += "\n"
+ html += '<b>Load:</b> %s %s' % (
+ status['ac_output_active_power']['value'],
+ status['ac_output_active_power']['unit'])
+ html += ' (%s%%)' % (status['output_load_percent']['value'],)
+
+ if status['pv1_input_power']['value'] > 0:
+ html += "\n"
+ html += '<b>Input power:</b> %s %s' % (
+ status['pv1_input_power']['value'],
+ status['pv1_input_power']['unit'])
+
+ if status['grid_voltage']['value'] > 0 or status['grid_freq']['value'] > 0:
+ html += "\n"
+ html += '<b>AC input:</b> %s %s' % (
+ status['grid_voltage']['value'],
+ status['grid_voltage']['unit'])
+ html += ', %s %s' % (
+ status['grid_freq']['value'],
+ status['grid_freq']['unit'])
+
+ html += "\n"
+ html += '<b>Priority:</b> %s' % (rated['output_source_priority'],)
+
+ html = html.replace("\n", '<br>')
+
+ return status, rated, html
+
+
class WebSite(http.HTTPServer):
_modems_config: ModemsConfig
@@ -108,10 +172,14 @@ class WebSite(http.HTTPServer):
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)
- self.get('/modems/info.ajx', self.get_modems_ajax)
- self.get('/modems/verbose.cgi', self.get_modems_verbose)
+ self.get('/main.cgi', self.index)
+
+ self.get('/modems.cgi', self.modems)
+ self.get('/modems/info.ajx', self.modems_ajx)
+ self.get('/modems/verbose.cgi', self.modems_verbose)
+
+ self.get('/inverter.cgi', self.inverter)
+ self.get('/inverter.ajx', self.inverter_ajx)
async def render_page(self,
req: http.Request,
@@ -129,16 +197,16 @@ class WebSite(http.HTTPServer):
response = aiohttp_jinja2.render_template(template_name+'.j2', req, context=context)
return response
- async def get_index(self, req: http.Request):
+ async def index(self, req: http.Request):
return await self.render_page(req, 'index',
title="Home web site")
- async def get_modems(self, req: http.Request):
+ async def modems(self, req: http.Request):
return await self.render_page(req, 'modems',
title='Состояние модемов',
context=dict(modems=self._modems_config))
- async def get_modems_ajax(self, req: http.Request):
+ async def modems_ajx(self, req: http.Request):
modem = req.query.get('id', None)
if modem not in self._modems_config.getkeys():
raise ValueError('invalid modem id')
@@ -154,7 +222,7 @@ class WebSite(http.HTTPServer):
return self.ok({'html': html})
- async def get_modems_verbose(self, req: http.Request):
+ async def modems_verbose(self, req: http.Request):
modem = req.query.get('id', None)
if modem not in self._modems_config.getkeys():
raise ValueError('invalid modem id')
@@ -175,6 +243,26 @@ class WebSite(http.HTTPServer):
title=f'Подробная информация о модеме "{modem_name}"',
context=dict(data=data, modem_name=modem_name))
+ async def inverter(self, req: http.Request):
+ action = req.query.get('do', None)
+ if action == 'set-osp':
+ val = req.query.get('value')
+ if val not in ('sub', 'sbu'):
+ raise ValueError('invalid osp value')
+ cl = get_inverter_client()
+ cl.exec('set-output-source-priority',
+ arguments=(val.upper(),))
+ raise HTTPFound('/inverter.cgi')
+
+ status, rated, html = await asyncio.get_event_loop().run_in_executor(None, get_inverter_data)
+ return await self.render_page(req, 'inverter',
+ title='Инвертор',
+ context=dict(status=status, rated=rated, html=html))
+
+ async def inverter_ajx(self, req: http.Request):
+ status, rated, html = await asyncio.get_event_loop().run_in_executor(None, get_inverter_data)
+ return self.ok({'html': html})
+
if __name__ == '__main__':
config.load_app(WebKbnConfig)