ospaz-site/logs_service/services.py

144 lines
4.4 KiB
Python

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=(datetime.now() - 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"[{datetime.now().isoformat()}] MbService:{type(self).__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"[{datetime.now().isoformat()}] MbService:{type(self).__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()
class MbTankService(MbService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._curr_state = None
# {
# "level": int,
# "status": int,
# "radar": int
# }
def _init_state(self):
pass
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]
}
def _check_need_save(self):
return True
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"]
]
}