# #! /usr/bin/env python # # -*- coding: utf-8 -*- # import os # import json # import httpx # import asyncio # import requests # import websockets # from copy import deepcopy # from fastapi import FastAPI # from dotenv import load_dotenv # from datetime import datetime, timedelta # import csv # app = FastAPI() # ############################################################################ # # VARIABLES # ############################################################################ # dotenv_path = os.path.join(os.path.dirname(__file__), '.env') # load_dotenv(dotenv_path) # lochost = os.getenv('lochost') # locport = os.getenv('locport') # jamhost = os.getenv('jamhost') # jamport = os.getenv('jamport') # master_server_ip = os.getenv('master_server_ip') # master_server_port = os.getenv('master_server_port') # freqs = [str(x) for x in os.getenv('freqs').split(',')] # num_of_clear_packs = int(os.getenv('num_of_clear_packs')) # threshold_to_alarm = int(os.getenv('threshold_to_alarm')) # time_to_jam = int(os.getenv('time_to_jam')) # time_to_fresh = int(os.getenv('time_to_fresh')) # active_interval_to_send = int(os.getenv('active_interval_to_send')) # passive_interval_to_send = int(os.getenv('passive_interval_to_send')) # jammer_timeout = int(os.getenv('jammer_timeout')) # master_timeout = int(os.getenv('master_timeout')) # amount_connection_attempts = int(os.getenv('amount_connection_attempts')) # debug_module_flag = bool(os.getenv('debug_module_flag')) # send_to_module_flag = bool(os.getenv('send_to_module_flag')) # send_to_master_flag = bool(os.getenv('send_to_master_flag')) # send_to_jammer_flag = bool(os.getenv('send_to_jammer_flag')) # latitude = float(os.getenv('latitude')) # longitude = float(os.getenv('longitude')) # flag = 0 # max_len_bulk = 1 # bulk_data = [] # sending_data_task = None # jam_server_connect = None # alarm = False # alarm_list = [] # jammer_event = False # data_queue = [None] * len(freqs) # freqs_alarm = {freq: 0 for freq in freqs} # #TODO: # # 1. Вырезать flag, если нужно и возможно. # # 2. Пофиксить костыль с asyncio.create_task(sending_data) - после jammer_event'a перестает подавать признаки жизни, # # поэтому гасим, когда включается глушилка и запускаем заново, когда глушилка отключается. # # 3. Пофиксить момент с data_queue:из-за асинхронных функций и старой реализации сервака происходит так ,что # # прилетает пакет аларма, система это видит, хочет его отправить, начинает отправку и из-за того, что это немного # # долгий процесс, то успевает прилететь чистый пакет и на мастер улетает чистый пакет. # # 4. Добавить print, только если deub_module_flag. # ############################################################################ # # GPS MODULE - INACTIVE # ############################################################################ # # Создание планировщика # # scheduler = BackgroundScheduler(daemon=True) # # scheduler.start() # # @app.route('/get_gps', methods = ['POST']) # # @scheduler.scheduled_job(IntervalTrigger(minutes=1)) # # def update_gps_coordinates(): # # # data_gps = request.json # # result = { # # 'latitude': latitude, # # 'longitude': longitude # # } # # try: # # url = "http://{0}:{1}/data/gps/{2}".format(master_server_ip, master_server_port, mac_address) # # response = requests.post(url, json=result) # # if response.status_code == 200: # # print('gps успешно отправлен') # # else: # # print('gps не был отправлен') # # # # except Exception: # # print('gps не были отправлены из-за отстутствия сервера в поле видимости') # # return result # # # # # # @scheduler.scheduled_job(IntervalTrigger(seconds=10)) # # def send_gps_to_master(): # # try: # # subprocess.run(["python3", "GPS_get_coords.py"]) # # #mac_address = get_mac_address() # # data_gps = update_gps_coordinates() # # url = "http://{0}:{1}/data/gps/{2}".format(master_server_ip, master_server_port, mac_address) # # response = requests.post(url, json=data_gps) # # if response.status_code == 200: # # print('gps успешно отправлен') # # else: # # print('gps не был отправлены по какой-то причине') # # except Exception: # # print('gps не были отправлены по причине отсутствия сервера в поле видимости') # # # ############################################################################ # # MODULE RIGISTR # ############################################################################ # def get_mac_address(interface='eth0'): # """ # Получить мак текущего устройства, на котором развернут модуль сервер. # :param interface: # """ # try: # result = os.popen('sudo ifconfig ' + interface).read() # mac_index = result.find('ether') # Индекс начала строки с MAC-адресом # if mac_index != -1: # mac_address = result[mac_index + 6:mac_index + 23] # return mac_address # else: # return None # except Exception as e: # print("Ошибка при получении MAC-адреса:" + str(e)) # return None # def get_ip_address(interface='eth0'): # """ # Получить айпишник текущего устройства, на котором развернут модуль сервер. # :param interface: # """ # try: # result = os.popen('sudo ifconfig ' + interface).read() # ip_index = result.find('inet') # Индекс начала строки с IP-адресом # if ip_index != -1: # ip_address = result[ip_index + 5:ip_index + 17] # return ip_address.strip() # else: # return None # except Exception as e: # print("Ошибка при получении IP-адреса:" + str(e)) # return None # def register_module(): # """ # Регистрация модуля на мастер сервере. # """ # data = {'mac': get_mac_address(), # 'ip': get_ip_address(), # 'moduleType': 'freq'} # try: # url = f"http://{master_server_ip}:{master_server_port}/module/register" # response = requests.post(url, json=data) # response.raise_for_status() # Проверка успешности запроса # print("Модуль зарегистрирован успешно = ", data) # except requests.exceptions.RequestException as e: # flag = 1 # print("Ошибка при регистрации модуля:" + str(e), data) # ############################################################################ # # SEND DATA TO MASTER # ############################################################################ # async def send_to_master(ModuleDataSingleV2, flag): # """ # Отправка данных на мастер по посту или через булк. По посту установлен лимит времени на отправку. В случае его # превышения - данные не отправлены. В случа неудачи отправки по любому из методов - данные не отправлены. # :param ModuleDataSingleV2: Пакет данных. # :param flag: # :return: # """ # mac_address = get_mac_address() # async with httpx.AsyncClient() as client: # for _ in range(amount_connection_attempts): # try: # if flag == 0: # url = f"http://{master_server_ip}:{master_server_port}/data/single/{mac_address}" # else: # url = f"http://{master_server_ip}:{master_server_port}/data/bulk/{mac_address}" # response = await client.post(url, json=ModuleDataSingleV2, timeout=master_timeout) # if response.status_code == 200: # print('Данные успешно отправлены') # flag = 0 # bulk_data.clear() # return 0 # else: # flag = 1 # if len(bulk_data) > max_len_bulk: # Если лимит bulk_data превышен, то удаляем первый элемент списка # bulk_data.pop(0) # bulk_data.append(ModuleDataSingleV2) # print('Данные не были отправлены по какой-то причине') # except Exception as e: # if len(bulk_data) > max_len_bulk: # Если лимит bulk_data превышен, то удаляем первый элемент списка # bulk_data.pop(0) # bulk_data.append(ModuleDataSingleV2) # flag = 1 # print('*'*100) # print('Данные не были отправлены по причине отсутствия сервера в поле видимости') # ############################################################################ # # PROCESS DATA # ############################################################################ # async def check_alarm(amplitude: int): # """ # Проверка амплитуды на превышение границы отработки системы. # :param amplitude: Амплитуда. # :return: Превышает/не превышает. # """ # if amplitude > threshold_to_alarm: # return True # else: # return False # async def agregate_data(data_to_agregate: list): # """ # Сбор пакета для отправки на мастер сервер. # :param data_to_agregate: Список из частотных пакетов. Длина списка = количесту обнаруживаемых частот. Может # содержать None, если частота ничего не присылает на модуль сервер. # :return: Пакет данных для отправки на мастер. # """ # data = [] # if any(item is not None for item in data_to_agregate): # for item in data_to_agregate: # if item is not None: # item['freq']=int(item['freq']) # data.append(item) # now = datetime.utcnow() - timedelta(seconds=2) # now = now.strftime("%Y-%m-%d %H:%M:%S") # data = { # "registeredAt": now, # "data": data # } # for i in range(len(freqs)): # data_queue[i] = None # return data # async def sending_data(): # #TODO: Надо по-хорошему нормально эту функцию переписать # """ # Отправка пакета данных на мастер сервер раз в некоторое время в определенном формате. Время отправки зависит # от текущего статуса тревоги (аларм/не аларм). # """ # global alarm # global jammer_event # global alarm_list # while True: # print('while true!') # print(data_queue) # # Если перед отправкой на мастер все было чисто, то ждем 60 сек. # # Если во время этих 60 сек. пришел пакет с алармом, то рассматриваем ситуации: # if not alarm: # alarm_list = [] # ModuleDataSingleV2 = await agregate_data(deepcopy(data_queue)) # print(f'На Мастер будет отправлена следующая информация: {ModuleDataSingleV2}') # await send_to_master(ModuleDataSingleV2, flag) # for i in range(passive_interval_to_send, 0, -1): # print('ТАЙМЕР ', i) # await asyncio.sleep(1) # if alarm: # break # # Если стоит флаг отправить данные на джеммер и при этом еще не был получен ивент на глушилку, то # # отправляем на джеммер данные. # else: # print(alarm_list) # data = deepcopy(data_queue) # for i in alarm_list: # try: # p = list(map(lambda x: str(x['freq']), data)).index(i) # print(p) # data[p]['amplitude'] = 9 # data[p]['triggered'] = True # except ValueError: # data.append({'freq': i, 'amplitude': 9, 'triggered': True}) # print(data) # alarm_list = [] # ModuleDataSingleV2 = await agregate_data(deepcopy(data)) # print(f'На Мастер будет отправлена следующая информация: {ModuleDataSingleV2}') # await send_to_master(ModuleDataSingleV2, flag) # if await send_jam_server_alarm(): # print('Отправили на сервис подавления и все дошло успешно') # else: # print('Не смогли отправить на сервис подавления') # continue # # В случае аларма ждем секунду перед новой отправкой данных. # await asyncio.sleep(active_interval_to_send) # @app.post('/waterfall') # async def waterfall(data: dict): # print('Received data: ', data) # @app.post('/process_data') # async def process_data(data: dict): # """ # Прием данных со скриптов детекции в формате data = {"freq": freq, # "amplitude": amplitude # } # где freq - строка, amplitude - int и их первичная обработка. # :param data: словарь с двумя ключами и значениями. # """ # global alarm # global alarm_list # print('Received data: ', data) # data_dict = deepcopy(data) # # Агрегируем N пакетов данных от частот в один общий список, он используется в функции agregate data. # # Каждая позиция списка фиксируется за отдельной частотой. # freq = data_dict['freq'] # for i in range(len(freqs)): # if freq == freqs[i]: # #Так делаем потому, что сервак является центром принятия решений по триггеру. # trigger = await check_alarm(data_dict['amplitude']) # data_dict.update({'triggered': trigger}) # data_queue[i] = deepcopy(data_dict) # data_dict.clear() # # Если прилетел триггер и глушилка не включена, то запускаем/обновляем счетчик чистых пакетов на этой # # частоте. # if trigger and not jammer_event: # freqs_alarm[freq] = num_of_clear_packs # print(f'freqs_alarm выглядит следующим обазом: {freqs_alarm}') # #Если прилетел триггер и модуль еще не заалармлен, то алармим. # if trigger and not alarm: # print('Приелет триггерa со сканнера. Работаем, ребята!') # alarm = True # alarm_list.append(str(freq)) # # Если прилетел триггер и модуль заалармлен, но при этом глушилка не работает и счетчик чистых пакетов # # данной частоты не равен нулю, то уменьшаем его. А когда в словаре счетчиков все нули, то убираем alarm. # elif not trigger and alarm and not jammer_event and freqs_alarm[freq] != 0: # freqs_alarm[freq] -= 1 # print(f'Чистый пакет. Уменьшаем в выбранной частоте: {freqs_alarm}') # if all(value == 0 for value in freqs_alarm.values()): # alarm = False # print(f'Прилетело {num_of_clear_packs}. Отключаем аларм и freqs_alarm выглядит так: {freqs_alarm}') # else: # continue # print('После получения данных data_queue выглядит следующим образом: ', data_queue) # ############################################################################ # # JAMMER # ############################################################################ # async def jammer_active(): # """ # Включение подавителя. # Отменяем таску на отправку данных на мастер. Зануляем словарь чистых пакетов и объявляем о прилете ивента с сервиса # подавления. # """ # global jammer_event # global freqs_alarm # global sending_data_task # if sending_data_task is not None: # sending_data_task.cancel() # freqs_alarm = {freq: 0 for freq in freqs} # # with open('university_records.csv', 'w', newline='') as csvfile: # # fieldnames = ['freq', 'branch', 'year', 'cgpa'] # # writer = csv.DictWriter(csvfile, fieldnames=fieldnames) # # writer.writeheader() # # writer.writerows(data) # jammer_event = True # print('АКТИВИРУЕМ ПОДАВИТЕЛЬ ААААААААААААААААААААААААААААААААААААААААААААААА!!!!') # print('-' * 20) # print('Статус по переменным:') # print(f'freqs_alarm: {freqs_alarm}') # print(f'jammer_event: {jammer_event}') # print(f'alarm: {alarm}') # print('-' * 20) # async def jammer_deactive(): # """ # Отключение подавителя. # Отрубаем аларм на модуле, отрубаем ивент сервера подавителей и запускаем таску отправки данных на мастер. # :return: # """ # global jammer_event # global alarm # global sending_data_task # alarm = False # jammer_event = False # sending_data_task = asyncio.create_task(sending_data()) # print('ОТКЛЮЧАЕМ ПОДАВИТЕЛЬ ААААААААААААААААААААААААААААААААААААААААААААААААА!!!!') # print('-' * 20) # print('Статус по переменным:') # print(f'freqs_alarm: {freqs_alarm}') # print(f'jammer_event: {jammer_event}') # print(f'alarm: {alarm}') # print('-' * 20) # async def send_jam_server_alarm(): # """ # Отправка алармовского пакета на сервер подавления по вебсокету. На отправку дается jammer_timeout секунд. # При неудаче - данные не отправлены. # """ # global jam_server_connect # msg = {'type': 'freq_alarm', # 'data': True} # # if jam_server_connect: # # try: # # await jam_server_connect.send(json.dumps(msg)) # # await asyncio.wait_for(jam_server_connect.recv(), jammer_timeout) # # return True # # except (asyncio.TimeoutError, websockets.exceptions.WebSocketException) as e: # # print(f"WebSocket error or timeout: {e}") # # return False # # else: # # return False # async with httpx.AsyncClient() as client: # try: # url = f"http://{jamhost}:{jamport}/jammer/unsafe_run" # response = await client.post(url, timeout=jammer_timeout) # if response.status_code in [200, 208]: # print('Данные успешно отправлены') # return True # else: # print('Данные не были отправлены по какой-то причине') # except (httpx.RequestError, asyncio.TimeoutError) as e: # print('Данные не были отправлены по причине отсутствия сервера в поле видимости') # except Exception as e: # print('Ошибка ', str(e)) # async def jam_server(): # """ # Прием данных по вебсокету с сервера подавления и их обработка. Включение/отключение подавителя. # При разрыве соединения принудительно отключаем подавитель. # """ # uri = f'ws://{jamhost}:{jamport}/ws' # global jam_server_connect # while True: # try: # jam_server_connect = await websockets.connect(uri) # while True: # data_from_jam_server = await jam_server_connect.recv() # data_from_jam_server = json.loads(data_from_jam_server) # print('Принял с сервера глушилок: ', data_from_jam_server) # if data_from_jam_server['type'] == 'run': # alarm_status = (data_from_jam_server['data'])['state'] # print(alarm_status) # if alarm_status: # await jammer_active() # else: # await asyncio.sleep(5) # await jammer_deactive() # except Exception as e: # jam_server_connect = None # if jammer_event: # await jammer_deactive() # @app.on_event("startup") # async def startup_event(): # """ # Запускаем параллельно задачи jam_server и sending_data. # """ # global sending_data_task # asyncio.create_task(jam_server()) # sending_data_task = asyncio.create_task(sending_data()) # if __name__ == '__main__': # import uvicorn # # update_gps_coordinates() # register_module() # Регистрация модуля на сервере # uvicorn.run(app, host=lochost, port=int(locport)) #! /usr/bin/env python # -*- coding: utf-8 -*- import os import json import httpx import uvicorn import asyncio import requests import websockets from copy import deepcopy from fastapi import FastAPI from dotenv import load_dotenv from datetime import datetime, timedelta import warnings warnings.filterwarnings("ignore", category=DeprecationWarning) app = FastAPI() ############################################################################ # VARIABLES ############################################################################ dotenv_path = os.path.join(os.path.dirname(__file__), '.env') load_dotenv(dotenv_path) lochost = os.getenv('lochost') locport = os.getenv('locport') jamhost = os.getenv('jamhost') jamport = os.getenv('jamport') master_server_ip = os.getenv('master_server_ip') master_server_port = os.getenv('master_server_port') freqs = [str(x) for x in os.getenv('freqs').split(',')] num_of_clear_packs = int(os.getenv('num_of_clear_packs')) threshold_to_alarm = int(os.getenv('threshold_to_alarm')) time_to_jam = int(os.getenv('time_to_jam')) time_to_fresh = int(os.getenv('time_to_fresh')) active_interval_to_send = int(os.getenv('active_interval_to_send')) passive_interval_to_send = int(os.getenv('passive_interval_to_send')) jammer_timeout = int(os.getenv('jammer_timeout')) master_timeout = int(os.getenv('master_timeout')) debug_module_flag = bool(os.getenv('debug_module_flag')) send_to_module_flag = bool(os.getenv('send_to_module_flag')) send_to_master_flag = bool(os.getenv('send_to_master_flag')) send_to_jammer_flag = bool(os.getenv('send_to_jammer_flag')) latitude = float(os.getenv('latitude')) longitude = float(os.getenv('longitude')) p = 1 flag = 0 max_len_bulk = 1 bulk_data = [] sending_data_task = None jam_server_connect = None alarm = False jammer_event = False data_queue = [None] * len(freqs) freqs_alarm = {freq: 0 for freq in freqs} #TODO: # 1. Вырезать flag, если нужно и возможно. # 2. Пофиксить костыль с asyncio.create_task(sending_data) - после jammer_event'a перестает подавать признаки жизни, # поэтому гасим, когда включается глушилка и запускаем заново, когда глушилка отключается. # 3. Пофиксить момент с data_queue:из-за асинхронных функций и старой реализации сервака происходит так ,что # прилетает пакет аларма, система это видит, хочет его отправить, начинает отправку и из-за того, что это немного # долгий процесс, то успевает прилететь чистый пакет и на мастер улетает чистый пакет. # 4. Добавить print, только если deub_module_flag. ############################################################################ # GPS MODULE - INACTIVE ############################################################################ # Создание планировщика # scheduler = BackgroundScheduler(daemon=True) # scheduler.start() # @app.route('/get_gps', methods = ['POST']) # @scheduler.scheduled_job(IntervalTrigger(minutes=1)) # def update_gps_coordinates(): # # data_gps = request.json # result = { # 'latitude': latitude, # 'longitude': longitude # } # try: # url = "http://{0}:{1}/data/gps/{2}".format(master_server_ip, master_server_port, mac_address) # response = requests.post(url, json=result) # if response.status_code == 200: # print('gps успешно отправлен') # else: # print('gps не был отправлен') # # except Exception: # print('gps не были отправлены из-за отстутствия сервера в поле видимости') # return result # # # @scheduler.scheduled_job(IntervalTrigger(seconds=10)) # def send_gps_to_master(): # try: # subprocess.run(["python3", "GPS_get_coords.py"]) # #mac_address = get_mac_address() # data_gps = update_gps_coordinates() # url = "http://{0}:{1}/data/gps/{2}".format(master_server_ip, master_server_port, mac_address) # response = requests.post(url, json=data_gps) # if response.status_code == 200: # print('gps успешно отправлен') # else: # print('gps не был отправлены по какой-то причине') # except Exception: # print('gps не были отправлены по причине отсутствия сервера в поле видимости') # ############################################################################ # MODULE RIGISTR ############################################################################ def get_mac_address(interface='enp5s0'): """ Получить мак текущего устройства, на котором развернут модуль сервер. :param interface: """ try: result = os.popen('sudo ifconfig ' + interface).read() mac_index = result.find('ether') # Индекс начала строки с MAC-адресом if mac_index != -1: mac_address = result[mac_index + 6:mac_index + 23] return mac_address else: return None except Exception as e: print("Ошибка при получении MAC-адреса:" + str(e)) return None def get_ip_address(interface='enp5s0'): """ Получить айпишник текущего устройства, на котором развернут модуль сервер. :param interface: """ try: result = os.popen('sudo ifconfig ' + interface).read() ip_index = result.find('inet') # Индекс начала строки с IP-адресом if ip_index != -1: ip_address = result[ip_index + 5:ip_index + 19] return ip_address.strip() else: return None except Exception as e: print("Ошибка при получении IP-адреса:" + str(e)) return None def register_module(): """ Регистрация модуля на мастер сервере. """ data = {'mac': get_mac_address(), 'ip': get_ip_address(), 'moduleType': 'freq'} try: url = f"http://{master_server_ip}:{master_server_port}/module/register" response = requests.post(url, json=data) response.raise_for_status() # Проверка успешности запроса print("Модуль зарегистрирован успешно = ", data) except requests.exceptions.RequestException as e: flag = 1 print("Ошибка при регистрации модуля:" + str(e), data) ############################################################################ # SEND DATA TO MASTER ############################################################################ async def send_to_master(ModuleDataSingleV2, flag): """ Отправка данных на мастер по посту или через булк. По посту установлен лимит времени на отправку. В случае его превышения - данные не отправлены. В случа неудачи отправки по любому из методов - данные не отправлены. :param ModuleDataSingleV2: Пакет данных. :param flag: :return: """ mac_address = get_mac_address() async with httpx.AsyncClient() as client: try: if flag == 0: url = f"http://{master_server_ip}:{master_server_port}/data/single/{mac_address}" else: url = f"http://{master_server_ip}:{master_server_port}/data/bulk/{mac_address}" response = await client.post(url, json=ModuleDataSingleV2, timeout=master_timeout) if response.status_code == 200: print('Данные успешно отправлены') flag = 0 bulk_data.clear() else: print(response.text) flag = 1 if len(bulk_data) > max_len_bulk: # Если лимит bulk_data превышен, то удаляем первый элемент списка bulk_data.pop(0) bulk_data.append(ModuleDataSingleV2) print('Данные не были отправлены по какой-то причине') except (httpx.RequestError, asyncio.TimeoutError) as e: if len(bulk_data) > max_len_bulk: # Если лимит bulk_data превышен, то удаляем первый элемент списка bulk_data.pop(0) bulk_data.append(ModuleDataSingleV2) flag = 1 print('Данные не были отправлены по причине отсутствия сервера в поле видимости') ############################################################################ # PROCESS DATA ############################################################################ async def check_alarm(amplitude: int): """ Проверка амплитуды на превышение границы отработки системы. :param amplitude: Амплитуда. :return: Превышает/не превышает. """ if amplitude > threshold_to_alarm: return True else: return False async def agregate_data(data_to_agregate: list): """ Сбор пакета для отправки на мастер сервер. :param data_to_agregate: Список из частотных пакетов. Длина списка = количесту обнаруживаемых частот. Может содержать None, если частота ничего не присылает на модуль сервер. :return: Пакет данных для отправки на мастер. """ data = [] if any(item is not None for item in data_to_agregate): for item in data_to_agregate: if item is not None: item['freq']=int(item['freq']) data.append(item) now = datetime.utcnow() - timedelta(seconds=2) now = now.strftime("%Y-%m-%d %H:%M:%S") data = { "registeredAt": now, "data": data } for i in range(len(freqs)): data_queue[i] = None return data async def sending_data(): #TODO: Надо по-хорошему нормально эту функцию переписать """ Отправка пакета данных на мастер сервер раз в некоторое время в определенном формате. Время отправки зависит от текущего статуса тревоги (аларм/не аларм). """ global alarm global jammer_event while True: print('while true!') ModuleDataSingleV2 = await agregate_data(deepcopy(data_queue)) if send_to_master_flag: print(f'На Мастер будет отправлена следующая информация: {ModuleDataSingleV2}') await send_to_master(ModuleDataSingleV2, flag) # Если перед отправкой на мастер все было чисто, то ждем 60 сек. # Если во время этих 60 сек. пришел пакет с алармом, то рассматриваем ситуации: if not alarm: for i in range(passive_interval_to_send, 0, -1): print('ТАЙМЕР ', i) await asyncio.sleep(1) if alarm: break # Если стоит флаг отправить данные на джеммер и при этом еще не был получен ивент на глушилку, то # отправляем на джеммер данные. elif alarm and send_to_jammer_flag and not jammer_event: if await send_jam_server_alarm(): print('Отправили на сервис подавления и все дошло успешно') else: print('Не смогли отправить на сервис подавления') # Сюда почему-то не заходит и вообще функция не подает признаков жизни после запуска подваителя(( if alarm and jammer_event: print('ПОДАВИТЕЛЬ РАБОТАЕТ РАЗБЕГАЙСЯ ААААААААААААААААААА') # В случае аларма ждем секунду перед новой отправкой данных. if alarm: await asyncio.sleep(active_interval_to_send) @app.post('/waterfall') async def waterfall(data: dict): print('Received data: ', data) @app.post('/process_data') async def process_data(data: dict): """ Прием данных со скриптов детекции в формате data = {"freq": freq, "amplitude": amplitude } где freq - строка, amplitude - int и их первичная обработка. :param data: словарь с двумя ключами и значениями. """ global alarm print('Received data: ', data) data_dict = deepcopy(data) # Агрегируем N пакетов данных от частот в один общий список, он используется в функции agregate data. # Каждая позиция списка фиксируется за отдельной частотой. freq = data_dict['freq'] for i in range(len(freqs)): if freq == freqs[i]: #Так делаем потому, что сервак является центром принятия решений по триггеру. trigger = await check_alarm(data_dict['amplitude']) data_dict.update({'triggered': trigger}) data_queue[i] = deepcopy(data_dict) data_dict.clear() # Если прилетел триггер и глушилка не включена, то запускаем/обновляем счетчик чистых пакетов на этой # частоте. if trigger and not jammer_event: freqs_alarm[freq] = num_of_clear_packs print(f'freqs_alarm выглядит следующим обазом: {freqs_alarm}') #Если прилетел триггер и модуль еще не заалармлен, то алармим. if trigger and not alarm: print('Приелет триггерa со сканнера. Работаем, ребята!') alarm = True # Если прилетел триггер и модуль заалармлен, но при этом глушилка не работает и счетчик чистых пакетов # данной частоты не равен нулю, то уменьшаем его. А когда в словаре счетчиков все нули, то убираем alarm. elif not trigger and alarm and not jammer_event and freqs_alarm[freq] != 0: freqs_alarm[freq] -= 1 print(f'Чистый пакет. Уменьшаем в выбранной частоте: {freqs_alarm}') if all(value == 0 for value in freqs_alarm.values()): alarm = False print(f'Прилетело {num_of_clear_packs}. Отключаем аларм и freqs_alarm выглядит так: {freqs_alarm}') else: continue print('После получения данных data_queue выглядит следующим образом: ', data_queue) ############################################################################ # JAMMER ############################################################################ async def jammer_active(): global p """ Включение подавителя. Отменяем таску на отправку данных на мастер. Зануляем словарь чистых пакетов и объявляем о прилете ивента с сервиса подавления. """ global jammer_event global freqs_alarm global sending_data_task if sending_data_task is not None: sending_data_task.cancel() p = 0 print(p) freqs_alarm = {freq: 0 for freq in freqs} jammer_event = True print('АКТИВИРУЕМ ПОДАВИТЕЛЬ ААААААААААААААААААААААААААААААААААААААААААААААА!!!!') print('-' * 20) print('Статус по переменным:') print(f'freqs_alarm: {freqs_alarm}') print(f'jammer_event: {jammer_event}') print(f'alarm: {alarm}') print('-' * 20) async def jammer_deactive(): global p """ Отключение подавителя. Отрубаем аларм на модуле, отрубаем ивент сервера подавителей и запускаем таску отправки данных на мастер. :return: """ global jammer_event global alarm global sending_data_task alarm = False jammer_event = False if p == 0: sending_data_task = asyncio.create_task(sending_data()) p = 1 #print(p) print('ОТКЛЮАЕМ ПОДАВИТЕЛЬ ААААААААААААААААААААААААААААААААААААААААААААААААА!!!!') print('-' * 20) print('Статус по переменным:') print(f'freqs_alarm: {freqs_alarm}') print(f'jammer_event: {jammer_event}') print(f'alarm: {alarm}') print('-' * 20) async def send_jam_server_alarm(): """ Отправка алармовского пакета на сервер подавления по вебсокету. На отправку дается jammer_timeout секунд. При неудаче - данные не отправлены. """ global jam_server_connect msg = {'type': 'freq_alarm', 'data': True} if jam_server_connect: try: await jam_server_connect.send(json.dumps(msg)) await asyncio.wait_for(jam_server_connect.recv()) return True except (asyncio.TimeoutError, websockets.exceptions.WebSocketException) as e: print(f"WebSocket error or timeout: {e}") return False else: return False async def jam_server(): """ Прием данных по вебсокету с сервера подавления и их обработка. Включение/отключение подавителя. При разрыве соединения принудительно отключаем подавитель. """ uri = f'ws://{jamhost}:{jamport}/ws' global jam_server_connect while True: try: jam_server_connect = await websockets.connect(uri) while True: data_from_jam_server = await jam_server_connect.recv() data_from_jam_server = json.loads(data_from_jam_server) print('Принял с сервера глушилок: ', data_from_jam_server) if data_from_jam_server['type'] == 'run': alarm_status = (data_from_jam_server['data'])['state'] print(alarm_status) if alarm_status: await jammer_active() else: await jammer_deactive() except Exception as e: jam_server_connect = None if jammer_event: await jammer_deactive() @app.on_event("startup") async def startup_event(): """ Запускаем параллельно задачи jam_server и sending_data. """ global sending_data_task asyncio.create_task(jam_server()) sending_data_task = asyncio.create_task(sending_data()) if __name__ == '__main__': # update_gps_coordinates() register_module() # Регистрация модуля на сервере uvicorn.run(app, host=lochost, port=int(locport))