aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Sorokin <me@ch1p.io>2024-01-18 04:14:38 +0300
committerEvgeny Sorokin <me@ch1p.io>2024-01-18 04:14:38 +0300
commitd237e81873a9e043f579e7f6a979f00510ddce08 (patch)
treef17ed95a80e1c594b585a829888da1c74f59798b
parenta9a241ad19449c29b68cd4a5b539bcbec816e341 (diff)
lws: sms page rewrite
-rw-r--r--bin/web_kbn.py64
-rw-r--r--include/py/homekit/config/config.py10
-rw-r--r--localwebsite/handlers/ModemHandler.php79
-rw-r--r--requirements.txt1
-rw-r--r--web/kbn_templates/index.j24
-rw-r--r--web/kbn_templates/sms.j2 (renamed from localwebsite/templates-web/sms_page.twig)31
6 files changed, 87 insertions, 102 deletions
diff --git a/bin/web_kbn.py b/bin/web_kbn.py
index 09fa9c6..c21269b 100644
--- a/bin/web_kbn.py
+++ b/bin/web_kbn.py
@@ -5,6 +5,7 @@ import aiohttp_jinja2
import json
import re
import inverterd
+import phonenumbers
import __py_include
from io import StringIO
@@ -27,6 +28,8 @@ class WebKbnConfig(AppConfigUnit):
'listen_addr': cls._addr_schema(required=True),
'assets_public_path': {'type': 'string'},
'pump_addr': cls._addr_schema(required=True),
+ 'inverter_grafana_url': {'type': 'string'},
+ 'sensors_grafana_url': {'type': 'string'},
}
@@ -69,8 +72,12 @@ def get_head_static() -> str:
return buf.getvalue()
+def get_modem_client(modem_cfg: dict) -> E3372:
+ return E3372(modem_cfg['ip'], legacy_token_auth=modem_cfg['legacy_auth'])
+
+
def get_modem_data(modem_cfg: dict, get_raw=False) -> Union[dict, tuple]:
- cl = E3372(modem_cfg['ip'], legacy_token_auth=modem_cfg['legacy_auth'])
+ cl = get_modem_client(modem_cfg)
signal = cl.device_signal
status = cl.monitoring_status
@@ -190,6 +197,8 @@ class WebSite(http.HTTPServer):
self.get('/inverter.cgi', self.inverter)
self.get('/inverter.ajx', self.inverter_ajx)
self.get('/pump.cgi', self.pump)
+ self.get('/sms.cgi', self.sms)
+ self.post('/sms.cgi', self.sms_post)
async def render_page(self,
req: http.Request,
@@ -208,8 +217,12 @@ class WebSite(http.HTTPServer):
return response
async def index(self, req: http.Request):
+ ctx = {}
+ for k in 'inverter', 'sensors':
+ ctx[f'{k}_grafana_url'] = config.app_config[f'{k}_grafana_url']
return await self.render_page(req, 'index',
- title="Home web site")
+ title="Home web site",
+ context=ctx)
async def modems(self, req: http.Request):
return await self.render_page(req, 'modems',
@@ -218,7 +231,7 @@ class WebSite(http.HTTPServer):
async def modems_ajx(self, req: http.Request):
modem = req.query.get('id', None)
- if modem not in self._modems_config.getkeys():
+ if modem not in self._modems_config.keys():
raise ValueError('invalid modem id')
modem_cfg = self._modems_config.get(modem)
@@ -234,7 +247,7 @@ class WebSite(http.HTTPServer):
async def modems_verbose(self, req: http.Request):
modem = req.query.get('id', None)
- if modem not in self._modems_config.getkeys():
+ if modem not in self._modems_config.keys():
raise ValueError('invalid modem id')
modem_cfg = self._modems_config.get(modem)
@@ -253,6 +266,49 @@ class WebSite(http.HTTPServer):
title=f'Подробная информация о модеме "{modem_name}"',
context=dict(data=data, modem_name=modem_name))
+ async def sms(self, req: http.Request):
+ modem = req.query.get('id', list(self._modems_config.keys())[0])
+ is_outbox = int(req.query.get('outbox', 0)) == 1
+ error = req.query.get('error', None)
+ sent = int(req.query.get('sent', 0)) == 1
+
+ cl = get_modem_client(self._modems_config[modem])
+ messages = cl.sms_list(1, 20, is_outbox)
+ return await self.render_page(req, 'sms',
+ title=f"SMS-сообщения ({'исходящие' if is_outbox else 'входящие'}, {modem})",
+ context=dict(
+ modems=self._modems_config,
+ selected_modem=modem,
+ is_outbox=is_outbox,
+ error=error,
+ is_sent=sent,
+ messages=messages
+ ))
+
+ async def sms_post(self, req: http.Request):
+ modem = req.query.get('id', list(self._modems_config.keys())[0])
+ is_outbox = int(req.query.get('outbox', 0)) == 1
+
+ fd = await req.post()
+ phone = fd.get('phone', None)
+ text = fd.get('text', None)
+
+ return_url = f'/sms.cgi?id={modem}&outbox={int(is_outbox)}'
+ phone = re.sub('\s+', '', phone)
+
+ if len(phone) > 4:
+ country = None
+ if not phone.startswith('+'):
+ country = 'RU'
+ number = phonenumbers.parse(phone, country)
+ if not phonenumbers.is_valid_number(number):
+ raise HTTPFound(f'{return_url}&error=Неверный+номер')
+ phone = phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
+
+ cl = get_modem_client(self._modems_config[modem])
+ cl.sms_send(phone, text)
+ raise HTTPFound(return_url)
+
async def inverter(self, req: http.Request):
action = req.query.get('do', None)
if action == 'set-osp':
diff --git a/include/py/homekit/config/config.py b/include/py/homekit/config/config.py
index eb2ad82..fec92a6 100644
--- a/include/py/homekit/config/config.py
+++ b/include/py/homekit/config/config.py
@@ -78,8 +78,14 @@ class BaseConfigUnit(ABC):
raise KeyError(f'option {key} not found')
- def getkeys(self):
- return list(self._data.keys())
+ def values(self):
+ return self._data.values()
+
+ def keys(self):
+ return self._data.keys()
+
+ def items(self):
+ return self._data.items()
class ConfigUnit(BaseConfigUnit):
diff --git a/localwebsite/handlers/ModemHandler.php b/localwebsite/handlers/ModemHandler.php
index 8179620..94ad75b 100644
--- a/localwebsite/handlers/ModemHandler.php
+++ b/localwebsite/handlers/ModemHandler.php
@@ -95,85 +95,6 @@ class ModemHandler extends RequestHandler
$this->tpl->render_page('routing_dhcp_page.twig');
}
- public function GET_sms() {
- global $config;
-
- list($selected, $is_outbox, $error, $sent) = $this->input('modem, b:outbox, error, b:sent');
- if (!$selected)
- $selected = array_key_first($config['modems']);
-
- $cfg = $config['modems'][$selected];
- $e3372 = new E3372($cfg['ip'], $cfg['legacy_token_auth']);
- $messages = $e3372->getSMSList(1, 20, $is_outbox);
-
- $this->tpl->set([
- 'modems_list' => array_keys($config['modems']),
- 'modems' => $config['modems'],
- 'selected_modem' => $selected,
- 'messages' => $messages,
- 'is_outbox' => $is_outbox,
- 'error' => $error,
- 'is_sent' => $sent
- ]);
-
- $direction = $is_outbox ? 'исходящие' : 'входящие';
- $this->tpl->set_title('SMS-сообщения ('.$direction.', '.$selected.')');
- $this->tpl->render_page('sms_page.twig');
- }
-
- public function POST_sms() {
- global $config;
-
- list($selected, $is_outbox, $phone, $text) = $this->input('modem, b:outbox, phone, text');
- if (!$selected)
- $selected = array_key_first($config['modems']);
-
- $return_url = '/sms/?modem='.$selected;
- if ($is_outbox)
- $return_url .= '&outbox=1';
-
- $go_back = function(?string $error = null) use ($return_url) {
- if (!is_null($error))
- $return_url .= '&error='.urlencode($error);
- else
- $return_url .= '&sent=1';
- redirect($return_url);
- };
-
- $phone = preg_replace('/\s+/', '', $phone);
-
- // при отправке смс на короткие номера не надо использовать libphonenumber и вот это вот всё
- if (strlen($phone) > 4) {
- $country = null;
- if (!startsWith($phone, '+'))
- $country = 'RU';
-
- $phoneUtil = PhoneNumberUtil::getInstance();
- try {
- $number = $phoneUtil->parse($phone, $country);
- } catch (NumberParseException $e) {
- debugError(__METHOD__.': failed to parse number '.$phone.': '.$e->getMessage());
- $go_back('Неверный номер ('.$e->getMessage().')');
- return;
- }
-
- if (!$phoneUtil->isValidNumber($number)) {
- $go_back('Неверный номер');
- return;
- }
-
- $phone = $phoneUtil->format($number, PhoneNumberFormat::E164);
- }
-
- $cfg = $config['modems'][$selected];
- $e3372 = new E3372($cfg['ip'], $cfg['legacy_token_auth']);
-
- $result = $e3372->sendSMS($phone, $text);
- debugLog($result);
-
- $go_back();
- }
-
protected static function getCurrentUpstream() {
global $config;
diff --git a/requirements.txt b/requirements.txt
index 8fa67c3..c242f38 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,6 +14,7 @@ psutil~=5.9.1
aioshutil~=1.1
scikit-image==0.21.0
cerberus~=1.3.4
+phonenumbers~=8.13.28
# following can be installed from debian repositories
# matplotlib~=3.5.0
diff --git a/web/kbn_templates/index.j2 b/web/kbn_templates/index.j2
index e3ab421..c356326 100644
--- a/web/kbn_templates/index.j2
+++ b/web/kbn_templates/index.j2
@@ -23,9 +23,9 @@
<h6 class="mt-4">Другое</h6>
<ul class="list-group list-group-flush">
- <li class="list-group-item"><a href="/inverter.cgi">Инвертор</a> (<a href="{{ grafana_inverter_url }}">Grafana</a>)</li>
+ <li class="list-group-item"><a href="/inverter.cgi">Инвертор</a> (<a href="{{ inverter_grafana_url }}">Grafana</a>)</li>
<li class="list-group-item"><a href="/pump.cgi">Насос</a></li>
- <li class="list-group-item"><a href="/sensors.cgi">Датчики</a> (<a href="{{ grafana_sensors_url }}">Grafana</a>)</li>
+ <li class="list-group-item"><a href="/sensors.cgi">Датчики</a> (<a href="{{ sensors_grafana_url }}">Grafana</a>)</li>
</ul>
<h6 class="mt-4"><a href="/cams/"><b>Все камеры</b></a> (<a href="/cams/?high=1">HQ</a>)</h6>
diff --git a/localwebsite/templates-web/sms_page.twig b/web/kbn_templates/sms.j2
index 112fa64..6de9d42 100644
--- a/localwebsite/templates-web/sms_page.twig
+++ b/web/kbn_templates/sms.j2
@@ -1,14 +1,13 @@
-{% include 'bc.twig' with {
- history: [
- {text: "SMS-сообщения" }
- ]
-} %}
+{% extends "base.j2" %}
+
+{% block content %}
+{{ breadcrumbs([{'text': 'SMS-сообщения'}]) }}
<nav>
<div class="nav nav-tabs" id="nav-tab">
- {% for modem in modems_list %}
- {% if selected_modem != modem %}<a href="/sms/?modem={{ modem }}" class="text-decoration-none">{% endif %}
- <button class="nav-link{% if modem == selected_modem %} active{% endif %}" type="button">{{ modems[modem].short_label }}</button>
+ {% for modem in modems.keys() %}
+ {% if selected_modem != modem %}<a href="/sms.cgi?id={{ modem }}" class="text-decoration-none">{% endif %}
+ <button class="nav-link{% if modem == selected_modem %} active{% endif %}" type="button">{{ modems.getshortname(modem) }}</button>
{% if selected_modem != modem %}</a>{% endif %}
{% endfor %}
</div>
@@ -20,14 +19,14 @@
<div class="alert alert-success" role="alert">
Сообщение отправлено.
</div>
-{% elseif error %}
+{% elif error %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endif %}
<div>
- <form method="post" action="/sms/">
+ <form method="post" action="/sms.cgi">
<input type="hidden" name="modem" value="{{ selected_modem }}">
<div class="form-floating mb-3">
<input type="text" name="phone" class="form-control" id="inputPhone" placeholder="+7911xxxyyzz">
@@ -46,17 +45,19 @@
<h6 class="text-primary mt-4">
Последние
{% if not is_outbox %}
- <b>входящие</b> <span class="text-black-50">|</span> <a href="/sms/?modem={{ selected_modem }}&amp;outbox=1">исходящие</a>
+ <b>входящие</b> <span class="text-black-50">|</span> <a href="/sms.cgi?id={{ selected_modem }}&amp;outbox=1">исходящие</a>
{% else %}
- <a href="/sms/?modem={{ selected_modem }}">входящие</a> <span class="text-black-50">|</span> <b>исходящие</b>
+ <a href="/sms.cgi?id={{ selected_modem }}">входящие</a> <span class="text-black-50">|</span> <b>исходящие</b>
{% endif %}
</h6>
{% for m in messages %}
<div class="mt-3">
- <b>{{ m.phone }}</b> <span class="text-secondary">({{ m.date }})</span><br/>
- {{ m.content }}
+ <b>{{ m.Phone }}</b> <span class="text-secondary">({{ m.Date }})</span><br/>
+ {{ m.Content }}
</div>
{% else %}
<span class="text-secondary">Сообщений нет.</span>
-{% endfor %} \ No newline at end of file
+{% endfor %}
+
+{% endblock %} \ No newline at end of file