diff --git a/index/urls.py b/index/urls.py index b44f8e0..aa5a998 100644 --- a/index/urls.py +++ b/index/urls.py @@ -18,8 +18,5 @@ from django.urls import path from . import views urlpatterns = [ - path('', views.view_index, name='index'), - path('fetch/stats', views.view_stats, name='fetch-stats'), - path('fetch/tank-chart', views.view_tank_chart, name='fetch-tank-chart'), - # path('methods/', views.call_method, name='call_method') + path('', views.view_index, name='index') ] diff --git a/index/views.py b/index/views.py index 53c8bd9..ae9201d 100644 --- a/index/views.py +++ b/index/views.py @@ -1,36 +1,9 @@ -import os - -from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden from django.shortcuts import render # from django.db.models import Manager -from django.contrib.auth.decorators import login_required, permission_required - -# только для тестирования! -import requests - -TEST_BASE_FETCH = "https://test.wawaa.ru/dev-fetch.php" +from django.contrib.auth.decorators import login_required @login_required def view_index(request): return render(request, 'index.html') - -@permission_required(perm='view_logs', raise_exception=True) -def view_stats(request): - # TODO: вставить использование привилегий для получения данных - # только для тестирования! - res = requests.get(TEST_BASE_FETCH + "?stats", headers={'Authorization': os.getenv("TEST_AUTH")}) - response = HttpResponse(res.content) - response.headers["Content-type"] = response.headers["Content-type"] - return response - - -@permission_required(perm='view_logs', raise_exception=True) -def view_tank_chart(request): - # только для тестирования! - days = request.GET.get('days', '7') - res = requests.get(TEST_BASE_FETCH + "?tank_chart=" + days, headers={'Authorization': os.getenv("TEST_AUTH")}) - response = HttpResponse(res.content) - response.headers["Content-type"] = response.headers["Content-type"] - return response diff --git a/logs_service/models.py b/logs_service/models.py index 754be42..c0e581a 100644 --- a/logs_service/models.py +++ b/logs_service/models.py @@ -1,5 +1,5 @@ from django.db import models -from datetime import datetime +from datetime import datetime, timedelta # select UNIX_TIMESTAMP(datetime), level_percentage, radar_low_reg, status_reg from tcs @@ -12,6 +12,26 @@ class MbTankRecord(models.Model): def __str__(self): return f"({self.id}) {self.dt}: radar={self.radar_raw}, level={self.level}" + @staticmethod + def load_stats(): + result = { + 'last_update': None, # последнее обновление, unix time + 'level': None, # текущее показание, пересчитанное в % + 'radar': None, # текущее показание с радара + 'status': None, # статусный регистр + 'last_radar_values': [] # последние показания за 15 минут + } + + last_save = MbTankRecord.objects.order_by('-dt').first() + if last_save is not None: + result['last_update'] = last_save.dt.timestamp() + result['level'] = last_save.level + result['radar'] = last_save.radar_raw + result['status'] = last_save.status + query = MbTankRecord.objects.filter(dt__gt=(datetime.now() - timedelta(minutes=15))).order_by('dt') + result['last_radar_values'] = [(int(item.dt.timestamp()), item.radar_raw) for item in query] + return result + class MbPumpRecord(models.Model): dt = models.DateTimeField(verbose_name="Время записи", default=datetime.now) diff --git a/logs_service/services.py b/logs_service/services.py index 0de1286..734b1b7 100644 --- a/logs_service/services.py +++ b/logs_service/services.py @@ -14,7 +14,7 @@ class MbClearHistoryService(Thread): def run(self): while True: - self.model.objects.filter(dt__lt=(timezone.now() - timezone.timedelta(days=60))).delete() + self.model.objects.filter(dt__lt=(datetime.now() - timedelta(days=60))).delete() time.sleep(10) @@ -79,21 +79,10 @@ class MbService(Thread): else: last_query = datetime.now() - def to_json(self): - return {} - class MbTankService(MbService): def __init__(self, **kwargs): super().__init__(**kwargs) - self.registers = {} - # { - # 'last_update': None, # последнее обновление, unix time - # 'level': None, # текущее показание, пересчитанное в % - # 'radar': None, # текущее показание с радара - # 'status': None, # статусный регистр - # 'last_radar_values': [] # последние показания за 15 минут - # } self._curr_state = None # { @@ -102,23 +91,8 @@ class MbTankService(MbService): # "radar": int # } - # для фильтрации уровня, чтобы его в бд писать - self.level_filter = [] - - def _update_last_radar_values(self): - res = [[item.dt.timestamp(), item.radar_raw] - for item in MbTankRecord.objects.filter(dt__gt=(datetime.now() - timedelta(minutes=15))).order_by('-dt')] - self.registers['last_radar_values'] = res - def _init_state(self): - self.last_save = MbTankRecord.objects.order_by('-dt').first() - print(f"Initializing MbTankService: last_save={self.last_save}") - if self.last_save is not None: - self.registers['last_update'] = self.last_save.dt - self.registers['level'] = self.last_save.level - self.registers['radar'] = self.last_save.radar_raw - self.registers['status'] = self.last_save.status - self._update_last_radar_values() + pass def _push_current_state(self): record = MbTankRecord(radar_raw=self._curr_state['radar'], @@ -137,14 +111,10 @@ class MbTankService(MbService): "status": values[5], "radar": (values[1] << 16) | values[2] } - self.registers['last_update'] = datetime.now() def _check_need_save(self): return True - def to_json(self): - return self.registers - class MbPumpService(MbService): _config = { diff --git a/logs_service/urls.py b/logs_service/urls.py new file mode 100644 index 0000000..f2b0bce --- /dev/null +++ b/logs_service/urls.py @@ -0,0 +1,23 @@ +"""logs_service URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" + +from django.urls import path +from . import views + +urlpatterns = [ + path('stats', views.view_stats, name='fetch-stats'), + path('tank-chart', views.view_tank_chart, name='fetch-tank-chart'), +] diff --git a/logs_service/views.py b/logs_service/views.py new file mode 100644 index 0000000..4604efe --- /dev/null +++ b/logs_service/views.py @@ -0,0 +1,40 @@ +import json + +from django.shortcuts import render +import os +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden +from django.contrib.auth.decorators import login_required, permission_required +from .models import MbTankRecord + +# только для тестирования! +import requests + +TEST_BASE_FETCH = "https://test.wawaa.ru/dev-fetch.php" + + +@permission_required(perm='logs_service.view_mbtankrecord', raise_exception=True) +def view_stats(request): + # TODO: вставить использование привилегий для получения данных + # только для тестирования! + ext_stats = requests.get(TEST_BASE_FETCH + "?stats", headers={'Authorization': os.getenv("TEST_AUTH")}) + + out = { + 'stats': { + 'tank': MbTankRecord.load_stats(), + 'pump': ext_stats.json()['stats']['pump'] + } + } + + response = HttpResponse(json.dumps(out)) + response.headers["Content-type"] = response.headers["Content-type"] + return response + + +@permission_required(perm='view_logs', raise_exception=True) +def view_tank_chart(request): + # только для тестирования! + days = request.GET.get('days', '7') + res = requests.get(TEST_BASE_FETCH + "?tank_chart=" + days, headers={'Authorization': os.getenv("TEST_AUTH")}) + response = HttpResponse(res.content) + response.headers["Content-type"] = response.headers["Content-type"] + return response diff --git a/ospaz_site/urls.py b/ospaz_site/urls.py index 6d122c8..0ffe2ac 100644 --- a/ospaz_site/urls.py +++ b/ospaz_site/urls.py @@ -22,5 +22,6 @@ from django.contrib.staticfiles.views import serve urlpatterns = [ path('', include('index.urls')), path('account/', include('users.urls')), + path('fetch/', include('logs_service.urls')), path('admin/', admin.site.urls), ] diff --git a/static/js/index-main.js b/static/js/index-main.js index 7093ba1..35f3868 100644 --- a/static/js/index-main.js +++ b/static/js/index-main.js @@ -133,22 +133,22 @@ const updateFunctions = { // Текущий уровень воды: % 'tank-level-now': (element, dataset) => { - element.innerHTML = dataset['tank']['last_percentage'] + element.innerHTML = dataset['tank']['level'] // тут все хорошо если влезаем в установленные рамки +-2% (69-80%) _setIndicatorClass(element, 67 <= dataset['tank']['last_percentage'] <= 82) }, // Текущее значение с радара 'tank-raw-now': (element, dataset) => { - element.innerHTML = dataset['tank']['last_radar'] + element.innerHTML = dataset['tank']['radar'] }, // Статус: 'tank-status': (element, dataset) => { const shur_status_bits = ['нужна вода', 'поплавок нижний', 'поплавок верхний', 'поплавок аварийный'] - element.innerHTML = unpackBits(dataset['tank']['status_reg'], shur_status_bits) + " (" + dataset['tank']['status_reg'] + ")" + element.innerHTML = unpackBits(dataset['tank']['status'], shur_status_bits) + " (" + dataset['tank']['status'] + ")" // тут все хорошо, пока нет аварийного поплавка - _setIndicatorClass(element, (dataset['tank']['status_reg'] & 0x8) === 0) + _setIndicatorClass(element, (dataset['tank']['status'] & 0x8) === 0) }, // Частота ПЧ: Гц