mirror of
				https://github.com/evraz-hack/backend.git
				synced 2025-11-04 01:27:26 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			337 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import asyncio
 | 
						|
import os
 | 
						|
import datetime
 | 
						|
import json
 | 
						|
import django
 | 
						|
import time
 | 
						|
 | 
						|
from channels.layers import get_channel_layer
 | 
						|
 | 
						|
from confluent_kafka.avro import Consumer
 | 
						|
from confluent_kafka.avro.serializer import SerializerError
 | 
						|
from django.utils.timezone import make_aware
 | 
						|
 | 
						|
print("loading values from DB, please wait")
 | 
						|
 | 
						|
# from inference import run
 | 
						|
 | 
						|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
 | 
						|
django.setup()
 | 
						|
 | 
						|
from exhauster_analytics.analytics.models import (
 | 
						|
    ExgausterSignal,
 | 
						|
    Record,
 | 
						|
    ExgausterRecordSignal,
 | 
						|
    RecordApproximation,
 | 
						|
    ExgausterRecordApproximationSignal,
 | 
						|
)
 | 
						|
from config.settings.base import structlog
 | 
						|
 | 
						|
log = structlog.get_logger()
 | 
						|
values = {}
 | 
						|
for sign in ExgausterSignal.objects.all():
 | 
						|
    if not sign.config:
 | 
						|
        values[sign.name] = []
 | 
						|
 | 
						|
em = len(Record.objects.all())
 | 
						|
if em > 60:
 | 
						|
    values["moment"] = [x.timestamp for x in Record.objects.all()[em - 60 :]]
 | 
						|
    for record in Record.objects.all()[em - 60 :]:
 | 
						|
        for sign in record.signals.all():
 | 
						|
            if not sign.signal.config and sign.signal.name in values:
 | 
						|
                values[sign.signal.name].append(sign.value)
 | 
						|
 | 
						|
 | 
						|
statuses = {}
 | 
						|
keys_not_to_send = []
 | 
						|
 | 
						|
for signal in ExgausterSignal.objects.filter(config__isnull=True):
 | 
						|
    if signal.characteristics_description:
 | 
						|
        statuses[signal.name] = {}
 | 
						|
        for installation in signal.installations.all():
 | 
						|
            keys_not_to_send.append(installation.name)
 | 
						|
            statuses[signal.name][installation.item_name] = installation.name
 | 
						|
 | 
						|
conf = {
 | 
						|
    "bootstrap.servers": "rc1a-2ar1hqnl386tvq7k.mdb.yandexcloud.net:9091",
 | 
						|
    "group.id": "MentalMind",
 | 
						|
    "session.timeout.ms": 6000,
 | 
						|
    "security.protocol": "SASL_SSL",
 | 
						|
    "ssl.ca.location": "CA.pem",
 | 
						|
    "sasl.mechanism": "SCRAM-SHA-512",
 | 
						|
    "sasl.username": "9433_reader",
 | 
						|
    "sasl.password": "eUIpgWu0PWTJaTrjhjQD3.hoyhntiK",
 | 
						|
    "auto.offset.reset": "end",
 | 
						|
}
 | 
						|
mapping = {
 | 
						|
    "SM_Exgauster[2:27]": "Подшипник 1 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:65]": "Подшипник 1 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:74]": "Подшипник 1 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:83]": "Подшипник 1 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:92]": "Подшипник 1 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:2]": "Подшипник 1 Вибрация Осевая vibration_axial",
 | 
						|
    "SM_Exgauster[2:139]": "Подшипник 1 Вибрация Осевая alarm_max",
 | 
						|
    "SM_Exgauster[2:151]": "Подшипник 1 Вибрация Осевая alarm_min",
 | 
						|
    "SM_Exgauster[2:163]": "Подшипник 1 Вибрация Осевая warning_max",
 | 
						|
    "SM_Exgauster[2:175]": "Подшипник 1 Вибрация Осевая warning_min",
 | 
						|
    "SM_Exgauster[2:0]": "Подшипник 1 Вибрация Горизонтальная vibration_horizontal",
 | 
						|
    "SM_Exgauster[2:137]": "Подшипник 1 Вибрация Горизонтальная alarm_max",
 | 
						|
    "SM_Exgauster[2:149]": "Подшипник 1 Вибрация Горизонтальная alarm_min",
 | 
						|
    "SM_Exgauster[2:161]": "Подшипник 1 Вибрация Горизонтальная warning_max",
 | 
						|
    "SM_Exgauster[2:173]": "Подшипник 1 Вибрация Горизонтальная warning_min",
 | 
						|
    "SM_Exgauster[2:1]": "Подшипник 1 Вибрация Вертикальная vibration_vertical",
 | 
						|
    "SM_Exgauster[2:138]": "Подшипник 1 Вибрация Вертикальная alarm_max",
 | 
						|
    "SM_Exgauster[2:150]": "Подшипник 1 Вибрация Вертикальная alarm_min",
 | 
						|
    "SM_Exgauster[2:162]": "Подшипник 1 Вибрация Вертикальная warning_max",
 | 
						|
    "SM_Exgauster[2:174]": "Подшипник 1 Вибрация Вертикальная warning_min",
 | 
						|
    "SM_Exgauster[2:28]": "Подшипник 2 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:66]": "Подшипник 2 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:75]": "Подшипник 2 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:84]": "Подшипник 2 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:93]": "Подшипник 2 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:5]": "Подшипник 2 Вибрация Осевая vibration_axial",
 | 
						|
    "SM_Exgauster[2:142]": "Подшипник 2 Вибрация Осевая alarm_max",
 | 
						|
    "SM_Exgauster[2:154]": "Подшипник 2 Вибрация Осевая alarm_min",
 | 
						|
    "SM_Exgauster[2:166]": "Подшипник 2 Вибрация Осевая warning_max",
 | 
						|
    "SM_Exgauster[2:178]": "Подшипник 2 Вибрация Осевая warning_min",
 | 
						|
    "SM_Exgauster[2:3]": "Подшипник 2 Вибрация Горизонтальная vibration_horizontal",
 | 
						|
    "SM_Exgauster[2:140]": "Подшипник 2 Вибрация Горизонтальная alarm_max",
 | 
						|
    "SM_Exgauster[2:152]": "Подшипник 2 Вибрация Горизонтальная alarm_min",
 | 
						|
    "SM_Exgauster[2:164]": "Подшипник 2 Вибрация Горизонтальная warning_max",
 | 
						|
    "SM_Exgauster[2:176]": "Подшипник 2 Вибрация Горизонтальная warning_min",
 | 
						|
    "SM_Exgauster[2:4]": "Подшипник 2 Вибрация Вертикальная vibration_vertical",
 | 
						|
    "SM_Exgauster[2:141]": "Подшипник 2 Вибрация Вертикальная alarm_max",
 | 
						|
    "SM_Exgauster[2:153]": "Подшипник 2 Вибрация Вертикальная alarm_min",
 | 
						|
    "SM_Exgauster[2:165]": "Подшипник 2 Вибрация Вертикальная warning_max",
 | 
						|
    "SM_Exgauster[2:177]": "Подшипник 2 Вибрация Вертикальная warning_min",
 | 
						|
    "SM_Exgauster[2:29]": "Подшипник 3 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:67]": "Подшипник 3 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:76]": "Подшипник 3 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:85]": "Подшипник 3 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:94]": "Подшипник 3 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:30]": "Подшипник 4 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:68]": "Подшипник 4 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:77]": "Подшипник 4 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:86]": "Подшипник 4 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:95]": "Подшипник 4 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:31]": "Подшипник 5 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:69]": "Подшипник 5 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:78]": "Подшипник 5 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:87]": "Подшипник 5 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:96]": "Подшипник 5 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:32]": "Подшипник 6 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:70]": "Подшипник 6 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:79]": "Подшипник 6 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:88]": "Подшипник 6 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:97]": "Подшипник 6 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:33]": "Подшипник 7 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:71]": "Подшипник 7 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:80]": "Подшипник 7 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:89]": "Подшипник 7 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:98]": "Подшипник 7 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:8]": "Подшипник 7 Вибрация Осевая vibration_axial",
 | 
						|
    "SM_Exgauster[2:145]": "Подшипник 7 Вибрация Осевая alarm_max",
 | 
						|
    "SM_Exgauster[2:157]": "Подшипник 7 Вибрация Осевая alarm_min",
 | 
						|
    "SM_Exgauster[2:169]": "Подшипник 7 Вибрация Осевая warning_max",
 | 
						|
    "SM_Exgauster[2:181]": "Подшипник 7 Вибрация Осевая warning_min",
 | 
						|
    "SM_Exgauster[2:6]": "Подшипник 7 Вибрация Горизонтальная vibration_horizontal",
 | 
						|
    "SM_Exgauster[2:143]": "Подшипник 7 Вибрация Горизонтальная alarm_max",
 | 
						|
    "SM_Exgauster[2:155]": "Подшипник 7 Вибрация Горизонтальная alarm_min",
 | 
						|
    "SM_Exgauster[2:167]": "Подшипник 7 Вибрация Горизонтальная warning_max",
 | 
						|
    "SM_Exgauster[2:179]": "Подшипник 7 Вибрация Горизонтальная warning_min",
 | 
						|
    "SM_Exgauster[2:7]": "Подшипник 7 Вибрация Вертикальная vibration_vertical",
 | 
						|
    "SM_Exgauster[2:144]": "Подшипник 7 Вибрация Вертикальная alarm_max",
 | 
						|
    "SM_Exgauster[2:156]": "Подшипник 7 Вибрация Вертикальная alarm_min",
 | 
						|
    "SM_Exgauster[2:168]": "Подшипник 7 Вибрация Вертикальная warning_max",
 | 
						|
    "SM_Exgauster[2:180]": "Подшипник 7 Вибрация Вертикальная warning_min",
 | 
						|
    "SM_Exgauster[2:34]": "Подшипник 8 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:72]": "Подшипник 8 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:81]": "Подшипник 8 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:90]": "Подшипник 8 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:99]": "Подшипник 8 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:11]": "Подшипник 8 Вибрация Осевая vibration_axial",
 | 
						|
    "SM_Exgauster[2:148]": "Подшипник 8 Вибрация Осевая alarm_max",
 | 
						|
    "SM_Exgauster[2:160]": "Подшипник 8 Вибрация Осевая alarm_min",
 | 
						|
    "SM_Exgauster[2:172]": "Подшипник 8 Вибрация Осевая warning_max",
 | 
						|
    "SM_Exgauster[2:184]": "Подшипник 8 Вибрация Осевая warning_min",
 | 
						|
    "SM_Exgauster[2:9]": "Подшипник 8 Вибрация Горизонтальная vibration_horizontal",
 | 
						|
    "SM_Exgauster[2:146]": "Подшипник 8 Вибрация Горизонтальная alarm_max",
 | 
						|
    "SM_Exgauster[2:158]": "Подшипник 8 Вибрация Горизонтальная alarm_min",
 | 
						|
    "SM_Exgauster[2:170]": "Подшипник 8 Вибрация Горизонтальная warning_max",
 | 
						|
    "SM_Exgauster[2:182]": "Подшипник 8 Вибрация Горизонтальная warning_min",
 | 
						|
    "SM_Exgauster[2:10]": "Подшипник 8 Вибрация Вертикальная vibration_vertical",
 | 
						|
    "SM_Exgauster[2:147]": "Подшипник 8 Вибрация Вертикальная alarm_max",
 | 
						|
    "SM_Exgauster[2:159]": "Подшипник 8 Вибрация Вертикальная alarm_min",
 | 
						|
    "SM_Exgauster[2:171]": "Подшипник 8 Вибрация Вертикальная warning_max",
 | 
						|
    "SM_Exgauster[2:183]": "Подшипник 8 Вибрация Вертикальная warning_min",
 | 
						|
    "SM_Exgauster[2:35]": "Подшипник 9 Температура нагрева Температура temperature",
 | 
						|
    "SM_Exgauster[2:73]": "Подшипник 9 Температура нагрева Температура alarm_max",
 | 
						|
    "SM_Exgauster[2:82]": "Подшипник 9 Температура нагрева Температура alarm_min",
 | 
						|
    "SM_Exgauster[2:91]": "Подшипник 9 Температура нагрева Температура warning_max",
 | 
						|
    "SM_Exgauster[2:100]": "Подшипник 9 Температура нагрева Температура warning_min",
 | 
						|
    "SM_Exgauster[2:42]": "Охладитель Масло  temperature_after",
 | 
						|
    "SM_Exgauster[2:41]": "Охладитель Масло  temperature_before",
 | 
						|
    "SM_Exgauster[2:37]": "Охладитель Вода  temperature_after",
 | 
						|
    "SM_Exgauster[2:36]": "Охладитель Вода temperature_before",
 | 
						|
    "SM_Exgauster[2:24]": "Газовый коллектор   temperature_before",
 | 
						|
    "SM_Exgauster[2:61]": "Газовый коллектор   underpressure_before",
 | 
						|
    "SM_Exgauster[4.1]": "Положение задвижки   gas_valve_closed",
 | 
						|
    "SM_Exgauster[4.2]": "Положение задвижки   gas_valve_open",
 | 
						|
    "SM_Exgauster[4:6]": "Положение задвижки   gas_valve_position",
 | 
						|
    "SM_Exgauster[4:2]": "Главный привод   rotor_current",
 | 
						|
    "SM_Exgauster[4:4]": "Главный привод   rotor_voltage",
 | 
						|
    "SM_Exgauster[4:3]": "Главный привод   stator_current",
 | 
						|
    "SM_Exgauster[4:5]": "Главный привод   stator_voltage",
 | 
						|
    "SM_Exgauster[4:0]": "Маслосистема   oil_level",
 | 
						|
    "SM_Exgauster[4:1]": "Маслосистема   oil_pressure",
 | 
						|
    "SM_Exgauster[2.0]": "Работа эксгаустера   work",
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
def my_assign(consumer, partitions):
 | 
						|
    for p in partitions:
 | 
						|
        p.offset = Record.objects.last().offset + 1
 | 
						|
    consumer.assign(partitions)
 | 
						|
 | 
						|
 | 
						|
async def send_to_channel_layer(data):
 | 
						|
    channel_layer = get_channel_layer()
 | 
						|
    await channel_layer.group_send("notifications", {"data": data, "type": "info"})
 | 
						|
 | 
						|
 | 
						|
async def send_to_channel_layer_approximation(data, approximation):
 | 
						|
    channel_layer = get_channel_layer()
 | 
						|
    await channel_layer.group_send(
 | 
						|
        f"approximation_{approximation}", {"data": data, "type": "info"}
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
c = Consumer(conf)
 | 
						|
 | 
						|
c.subscribe(["zsmk-9433-dev-01"], on_assign=my_assign)
 | 
						|
 | 
						|
signals = {}
 | 
						|
for ex in ExgausterSignal.objects.all():
 | 
						|
    if not ex.config:
 | 
						|
        if ex.place_x not in signals:
 | 
						|
            signals[ex.place_x] = {}
 | 
						|
        if ex.place_y not in signals[ex.place_x]:
 | 
						|
            signals[ex.place_x][ex.place_y] = {}
 | 
						|
        signals[ex.place_x][ex.place_y][ex.type] = ex
 | 
						|
 | 
						|
 | 
						|
# delete latest offset
 | 
						|
offset = Record.objects.last().offset
 | 
						|
Record.objects.filter(offset=offset).delete()
 | 
						|
RecordApproximation.objects.filter(offset=offset).delete()
 | 
						|
 | 
						|
while True:
 | 
						|
    try:
 | 
						|
        msg = c.poll(10)
 | 
						|
    except SerializerError as e:
 | 
						|
        log.info("Message deserialization failed for {}: {}".format(msg, e))
 | 
						|
        continue
 | 
						|
 | 
						|
    if msg is None:
 | 
						|
        continue
 | 
						|
 | 
						|
    if msg.error():
 | 
						|
        log.info("AvroConsumer error: {}".format(msg.error()))
 | 
						|
        continue
 | 
						|
    try:
 | 
						|
        data = json.loads(msg.value())
 | 
						|
    except json.JSONDecodeError:
 | 
						|
        log.info("Message deserialization failed for {}".format(msg))
 | 
						|
        continue
 | 
						|
    date = make_aware(
 | 
						|
        datetime.datetime.strptime(data["moment"], "%Y-%m-%dT%H:%M:%S.%f")
 | 
						|
        + datetime.timedelta(hours=3)
 | 
						|
    )
 | 
						|
    offset = msg.offset()
 | 
						|
    start = time.time()
 | 
						|
    print(f"DEBUG: received {offset}, {date}")
 | 
						|
    resp = {}
 | 
						|
    record = Record.objects.create(timestamp=date, offset=offset, message=data)
 | 
						|
    if offset != 0:
 | 
						|
        approximation_amounts = [
 | 
						|
            x for x, _ in RecordApproximation.AmountChoices.choices if offset % x == 0
 | 
						|
        ]
 | 
						|
    else:
 | 
						|
        approximation_amounts = []
 | 
						|
    approximation = {}
 | 
						|
    for amount in approximation_amounts:
 | 
						|
        approximation[amount] = RecordApproximation.objects.create(
 | 
						|
            amount=amount, timestamp=date, offset=offset
 | 
						|
        )
 | 
						|
    approximation_values = {}
 | 
						|
    for approximation_val in approximation_amounts:
 | 
						|
        approximation_values[approximation_val] = {}
 | 
						|
 | 
						|
    for key, val in data.items():
 | 
						|
        if "SM" in key and key not in keys_not_to_send:
 | 
						|
            resp[key] = val
 | 
						|
 | 
						|
            if key in values:
 | 
						|
                del values[key][0]
 | 
						|
            else:
 | 
						|
                values[key] = [0] * 60
 | 
						|
            values[key].append(val)
 | 
						|
 | 
						|
            if "." in key:
 | 
						|
                x, y = map(int, key[key.find("[") + 1 : key.find("]")].split("."))
 | 
						|
                type = "digital"
 | 
						|
            else:
 | 
						|
                x, y = map(int, key[key.find("[") + 1 : key.find("]")].split(":"))
 | 
						|
                type = "analog"
 | 
						|
            try:
 | 
						|
                signal = signals[x][y][type]
 | 
						|
                ExgausterRecordSignal.objects.create(
 | 
						|
                    record=record, signal=signal, value=val
 | 
						|
                )
 | 
						|
                if key in statuses:
 | 
						|
                    alarm_max = data[statuses[key]["alarm_max"]]
 | 
						|
                    alarm_min = data[statuses[key]["alarm_min"]]
 | 
						|
                    warning_max = data[statuses[key]["warning_max"]]
 | 
						|
                    warning_min = data[statuses[key]["warning_min"]]
 | 
						|
                    if val > alarm_max or val < alarm_min:
 | 
						|
                        resp[f"{key}_status"] = "alarm"
 | 
						|
                    elif val > warning_max or val < warning_min:
 | 
						|
                        resp[f"{key}_status"] = "warning"
 | 
						|
                    else:
 | 
						|
                        resp[f"{key}_status"] = "normal"
 | 
						|
                for amount, approx in approximation.items():
 | 
						|
                    vals = values[key][60 - amount :]
 | 
						|
                    r = sum(vals) / len(vals)
 | 
						|
                    approximation_values[amount][key] = r
 | 
						|
                    ExgausterRecordApproximationSignal.objects.create(
 | 
						|
                        record=approx, signal=signal, value=r
 | 
						|
                    )
 | 
						|
            except KeyError:
 | 
						|
                continue
 | 
						|
 | 
						|
    del values["moment"][0]
 | 
						|
    values["moment"].append(date)
 | 
						|
 | 
						|
    # call ml
 | 
						|
    # df = pandas.DataFrame.from_dict(values, orient="index").transpose()
 | 
						|
    # df.columns = ["moment"] + [
 | 
						|
    #     "".join([x for x in el if x != "\\"]) for el in df.columns if el != "moment"
 | 
						|
    # ]
 | 
						|
    # df = df.rename(columns=mapping)
 | 
						|
    # df["moment"] = pandas.to_datetime(df["moment"], utc=True)
 | 
						|
    # df = df.set_index("moment").resample("5T").first().reset_index()
 | 
						|
    # run(df)
 | 
						|
 | 
						|
    loop = asyncio.get_event_loop()
 | 
						|
    coroutine = send_to_channel_layer(resp)
 | 
						|
    loop.run_until_complete(coroutine)
 | 
						|
 | 
						|
    for approx, data in approximation_values.items():
 | 
						|
        loop = asyncio.get_event_loop()
 | 
						|
        coroutine = send_to_channel_layer_approximation(data, approx)
 | 
						|
        loop.run_until_complete(coroutine)
 | 
						|
 | 
						|
    print(f"DEBUG: done {offset}, {time.time() - start} sec taken")
 | 
						|
 | 
						|
c.close()
 |