Добавил еще одно устройство в проект: HART модем, получающий накопленный расход от расходометра.

This commit is contained in:
VladislavOstapov 2024-02-21 15:44:55 +03:00
parent 4da1ce477e
commit 0195373cc4
7 changed files with 87 additions and 11 deletions

View File

@ -12,15 +12,24 @@ DB_PORT=5432
# секретный ключ Django
DJANGO_SECRET="django-secure"
# включение/отключение сервисов ModBus
# Настройки сервисов modbus
# Резервуар
ENABLE_MB_TANK_SERVICE=1
MB_TANK_ADDRESS="10.8.105.3"
MB_TANK_PORT=504
MB_TANK_SCAN_RATE_MS=60000
# Насосная
ENABLE_MB_PUMP_SERVICE=1
MB_PUMP_ADDRESS="10.8.105.2"
MB_PUMP_PORT=503
MB_PUMP_SCAN_RATE_MS=5000
# Преобразователь HART-Modbus TCP для расходометра
ENABLE_MB_HART_SERVICE=1
MB_HART_ADDRESS="10.8.105.2"
MB_HART_PORT=602
MB_HART_SCAN_RATE_MS=5000
LOGGER_SAVE_DAYS=60

View File

@ -11,9 +11,11 @@ class LogsServiceConfig(AppConfig):
mb_tank_service = None
mb_pump_service = None
mb_hart_service = None
mb_tank_service_enable = True
mb_pump_service_enable = True
mb_tank_service_enable = False
mb_pump_service_enable = False
mb_hart_service_enable = False
def ready(self):
# защита от двойного запуска
@ -21,13 +23,16 @@ class LogsServiceConfig(AppConfig):
return
print(f"Running logger service in process with pid={os.getpid()}")
from .services import MbTankService, MbPumpService
from .services import MbTankService, MbPumpService, MbHartService
# включение/выключение сервисов
mb_tank_service_enable = os.getenv('ENABLE_MB_TANK_SERVICE', '1')
LogsServiceConfig.mb_tank_service_enable = int(mb_tank_service_enable) != 0
_en = os.getenv('ENABLE_MB_TANK_SERVICE', '1')
LogsServiceConfig.mb_tank_service_enable = int(_en) != 0
mb_pump_service_enable = os.getenv('ENABLE_MB_PUMP_SERVICE', '1')
LogsServiceConfig.mb_pump_service_enable = int(mb_pump_service_enable) != 0
_en = os.getenv('ENABLE_MB_PUMP_SERVICE', '1')
LogsServiceConfig.mb_pump_service_enable = int(_en) != 0
_en = os.getenv('ENABLE_MB_HART_SERVICE', '1')
LogsServiceConfig.mb_hart_service_enable = int(_en) != 0
save_days = int(os.getenv('LOGGER_SAVE_DAYS'))
@ -44,6 +49,12 @@ class LogsServiceConfig(AppConfig):
scan_rate=int(os.getenv('MB_PUMP_SCAN_RATE_MS')),
save_days=save_days)
if LogsServiceConfig.mb_hart_service_enable:
LogsServiceConfig.mb_hart_service = MbHartService(ip_addr=os.getenv('MB_HART_ADDRESS'),
port=int(os.getenv('MB_HART_PORT')),
scan_rate=int(os.getenv('MB_HART_SCAN_RATE_MS')),
save_days=save_days)
# запуск сервисов
if LogsServiceConfig.mb_tank_service_enable:
if DEBUG:
@ -55,6 +66,11 @@ class LogsServiceConfig(AppConfig):
print('Creating service MbPumpService...')
LogsServiceConfig.mb_pump_service.start()
if LogsServiceConfig.mb_hart_service_enable:
if DEBUG:
print('Creating service MbHartService...')
LogsServiceConfig.mb_hart_service.start()
return True

View File

@ -181,3 +181,27 @@ class MbPumpService(MbService):
'half_auto_control': None
}
class MbHartService(MbService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._lock = Lock()
self._curr_state = None
def _load_current_state(self):
# D?: flow_meter
values = self.mb.read_holding_registers(600, 1)
if values is None:
raise AssertionError('failed to load current state')
with self._lock:
self._curr_state = {
'accumulated_flow': values[0]
}
def get_stats(self):
with self._lock:
# копируем данные, если они есть в текущем состоянии (иначе пустые поля)
return self._curr_state or {
'accumulated_flow': None
}

View File

@ -10,16 +10,30 @@ from .apps import LogsServiceConfig
@permission_required(perm='logs_service.view_mbtankrecord', raise_exception=True)
def view_stats(request):
print(f"Executing view_stats in process with pid={os.getpid()}")
# данные резервуара
tank = {}
if request.user.has_perm('logs_service.view_mbtankrecord'):
if LogsServiceConfig.mb_pump_service is not None and LogsServiceConfig.mb_pump_service_enable:
tank = MbTankRecord.load_stats()
# данные насосной
pump = {}
if request.user.has_perm('logs_service.view_pump_stats'):
if LogsServiceConfig.mb_pump_service is not None and LogsServiceConfig.mb_pump_service_enable:
pump = LogsServiceConfig.mb_pump_service.get_stats()
# данные HART-модема, он же расходометр
hart = {}
if request.user.has_perm('logs_service.view_accumulated_flow'):
if LogsServiceConfig.mb_hart_service is not None and LogsServiceConfig.mb_hart_service_enable:
hart = LogsServiceConfig.mb_hart_service.get_stats()
out = {
'stats': {
'tank': tank,
'pump': pump
'pump': pump,
'hart': hart
}
}
response = HttpResponse(json.dumps(out))

View File

@ -355,6 +355,14 @@ const updateFunctions = {
}
},
'pump-accumulated-flow': {
'get_val': (dataset) => { return dataset['hart']['accumulated_flow'] },
'handler': (element, value) => {
element.innerHTML = value
return null
}
},
// 'id': {
// 'get_val': (dataset) => { return dataset['...']['...'] },
// 'handler': (element, value) => {

View File

@ -60,6 +60,9 @@
<p>Регистр аварий: <span id="pump-alarms"></span></p>
<p>Состояние КА: <span id="pump-stage"></span></p>
<p>Текущий расход: <span id="pump-flow-meter"></span>м³/ч</p>
{% if perms.logs_service.view_accumulated_flow %}
<p>Накопленный расход: <span id="pump-accumulated-flow"></span>м³</p>
{% endif %}
</div>
{% endif %}
</div>

View File

@ -62,7 +62,9 @@ class User(AbstractBaseUser):
'logs_service.delete_mbtankrecord': UserAccessLevel.ADMIN,
'logs_service.view_mbtankrecord': UserAccessLevel.BASIC,
'logs_service.view_pump_stats': UserAccessLevel.ENGINEER
'logs_service.view_pump_stats': UserAccessLevel.ENGINEER,
'logs_service.view_accumulated_flow': UserAccessLevel.ADMIN,
}
if perm in permissions:
if permissions[perm] <= self.access_level: