ospaz-site/logs_service/services.py

174 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from .models import *
from ospaz_site.settings import DEBUG
from threading import Thread
import time
from datetime import datetime, timedelta
from pyModbusTCP.client import ModbusClient
class MbClearHistoryService(Thread):
def __init__(self, model, save_days):
super().__init__()
self.model = model
self._days = save_days
def run(self):
while True:
self.model.objects.filter(dt__lt=(timezone.now() - timezone.timedelta(days=60))).delete()
time.sleep(10)
class MbService(Thread):
def __init__(self, ip_addr, port, scan_rate, poll_time_ms=60000, save_days=60):
super().__init__()
self._poll_time_ms = poll_time_ms
self._scan_rate = scan_rate
self.mb = ModbusClient(host=ip_addr, port=port, debug=DEBUG, auto_open=True)
def _init_state(self):
"""
Функция вызывается один раз при создании сервиса, в ней нужно загрузить содержимое регистров из базы данных.
"""
pass
def _push_current_state(self):
"""
Функция вызывается в момент, когда требуется сохранить состояние в базу данных
"""
pass
def _load_current_state(self):
"""
Функция должна совершить операцию чтения регистров modbus
"""
pass
def _check_need_save(self):
"""
Функция должна вернуть результат: нужно ли сохранять текущее состояние в базу данных
"""
return True
def run(self):
# if self.log_type == 'on-change':
# pass
# else:
print(f"[MbService:{self.__class__.name}] service started!")
self._init_state()
last_query = datetime.now()
scan_rate = timedelta(milliseconds=self._scan_rate)
while True:
try:
self._load_current_state()
if self._check_need_save():
self._push_current_state()
except Exception as ex:
print(f"[MbService:{self.__class__.name}] Exception: {ex}")
# вычислим время до следующего опроса и подождем
# время следующего опроса
need_time = last_query + scan_rate
curr_time = datetime.now()
if need_time > curr_time:
delta = need_time - curr_time
time.sleep(delta.seconds + (delta.microseconds / 1000000))
last_query = need_time
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
# {
# "level": int,
# "status": int,
# "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()
def _push_current_state(self):
record = MbTankRecord(radar_raw=self._curr_state['radar'],
level=self._curr_state['level'],
status=self._curr_state['status'])
record.save()
def _load_current_state(self):
# D0: level_percentage
# D5: status_reg
# D1: radar_high_reg
# D2: radar_low_reg
values = self.mb.read_holding_registers(0, 6)
self._curr_state = {
"level": values[0],
"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 = {
"modbus": {
"host": "10.8.105.2",
"port": 503,
"log-type": "on-change"
},
"registers": [
["D0", "v231_v236"],
["D1", "v236_v29"],
["D15", "ps_39"],
["D16", "flow_meter"],
["D28", "pump_stage"],
["D30", "half_auto_control"],
["D31", "watch_1"],
["D32", "watch_2"],
["D33", "st_valves"],
["D35", "alarms"],
["D25", "vfd_freq"],
["D26", "vfd_current"],
["D27", "vfd_error"]
]
}