def close(self): ION.TRACKERS.remove(self) self.sock.close() self.db.close() self.stop = True logger.info( f'ION {self.imei} отключен [{self.addr[0]}:{self.addr[1]}]')
def start(self): ADM.TRACKERS.add(self) self.db = pymysql.connect(**CONN) self.need_reply = 0 self.imei = self.handle_imei() if not self.imei is None: logger.info( f'ADM{self.model} {self.imei} подключен [{self.addr[0]}:{self.addr[1]}]' ) self.assign = get_configuration(self.NAME, self.imei, self.model) self.ign_v = get_ignition_v(self.imei) self.stop = False self.data = {} self.command_response = {} try: self.handle_packet() except Exception as e: self.close() logger.error('ADM ERROR {e}') raise e
def close(self): ADM.TRACKERS.remove(self) self.sock.close() self.db.close() self.stop = True logger.info( f'ADM{self.model} {self.imei} отключен [{self.addr[0]}:{self.addr[1]}]' )
def start(self): logger.info(f'WialonCombine подключен [{self.addr[0]}:{self.addr[1]}]') WialonCombine.TRACKERS.add(self) self.db = pymysql.connect(**CONN) self.pid = 0 self.stop = False self.handle_packet()
def handle_packet(self): if self.stop: self.stop = False while not self.stop: self.msg_type = 0 packet = binascii.hexlify(self.sock.recv(1024)) if len(packet) == 4: packet = binascii.hexlify(self.sock.recv(1024)) if len(packet) == 0: continue logger.debug( f'[ADM{self.model}] {self.imei} принят пакет {packet}') all_data = [] while len(packet) > 0: packet, data = self.data_main(packet) if packet is None: break logger.debug( f'[ADM{self.model}] {self.imei} основные данные обработаны\n{data}' ) logger.debug( f'[ADM{self.model}] {self.imei} статус пакета {data["typ"]}' ) bits = list(map(int, str(bin(data['typ']))[2:][::-1]))[2:] for n, bit in enumerate(bits): if bit: before = packet[:] packet, d = getattr(ADM, ADM.DATA_BLOCKS[n])(self, packet) logger.debug( f'[ADM{self.model}] {self.imei} блок {ADM.DATA_BLOCKS[n]}\nПакет до: {before}\nПакет после: {packet}\nДанные: {d}' ) data.update(d) data = self.rename_data(data) logger.debug( f'[ADM{self.model}] {self.imei} данные после переименования: {data}' ) data = self.prepare_geo(data) logger.debug( f'[ADM{self.model}] {self.imei} данные после обработки: {data}' ) all_data.append(data) if all_data: count = insert_geo(all_data) logger.info( f'ADM{self.model} {self.imei} принято {count}/{len(all_data)} записей' ) if self.need_reply == 1: pass elif self.need_reply == 2: self.sock.send(b'***' + str(count).encode('ascii') + b'*')
def start(self): self.imei = self.handle_imei() logger.info( f'Teltonika{self.model} {self.imei} подключен [{self.addr[0]}:{self.addr[1]}]' ) Teltonika.TRACKERS.add(self) self.assign = get_configuration(self.NAME, self.imei, self.model) self.decoder = self.get_decoder(self.model) self.ign_v = get_ignition_v(self.imei) self.lock = threading.Lock() self.stop = False main_th = threading.Thread(target=self.handle_packet) main_th.start()
def __init__(self, protocol_name: str): """Родитель всех протоколов protocol_name (str): имя протокола, как в папке PROTOCOLS_DIR без расширения """ assert isinstance(protocol_name, str) self.protocol_name = protocol_name self.packet = bytes() self.data = {} self.settings = {} self.protocol = Retranslator.get_json(self.PROTOCOLS_DIR, self.protocol_name + ".json") logger.info(f"Протокол {protocol_name} инициализирован\n")
def __init__(self, protocol, server, model=''): self.ip, self.port = server.split(':') self.model = model self.sock = socket.socket() self.sock.bind((self.ip, int(self.port))) self.sock.listen(1024) if self.ip == '': self.ip = 'ANY' logger.info( f'Сервер для {protocol.NAME}{model} запущен - [{self.ip}:{self.port}]\n' ) listen_th = threading.Thread(target=self.connecter, args=(protocol, model)) listen_th.start()
def send_command(self, command): packet = '' # packet = add_ushort(packet, 0x4040) # packet = add_ubyte(packet, 0xFF) # packet = add_ushort(packet, len(command)+5) # packet = add_uint(packet, int(time())) # packet = add_ubyte(packet, 0x00) packet = add_str(packet, command) # crc16_pack = struct.unpack(f'{len(packet)//2}s', binascii.a2b_hex(packet.encode('ascii')))[0] # packet = add_ushort(packet, crc16(crc16_pack)) # logger.info(f'[WialonCombine] командный пакет сформирован:\n{packet}\n') packet = pack(packet) try: self.sock.send(packet) logger.info(f'[WialonCombine] команда {command} отправлена\n') except Exception as e: logger.error( f'[WialonCombine] команда {command} не отправлена {str(e)}\n')
def start(self): GalileoSky.TRACKERS.add(self) self.db = pymysql.connect(**CONN) self.imei = self.handle_imei() logger.info( f'ADM{self.model} {self.imei} подключен [{self.addr[0]}:{self.addr[1]}]' ) self.assign = get_configuration(self.NAME, self.imei) self.ign_v = get_ignition_v(self.imei) self.stop = False self.data = {} try: self.handle_packet() except Exception as e: self.close() raise e
def run(self): logger.info( f"START {self.retranslator.protocol_name} {self.imei} [{self.ip}:{self.port}]" ) while True: while self.socket == -1: self.socket = self.connect() sleep(Tracker.CONN_DELAY) while self.queue.qsize() == 0: self.fill_queue() row = self.queue.get() if row.get('reserve', None): row['imei'] = str(row['imei']) row['reserve'] = loads('{' + row['reserve'] + '}') row.update(row['reserve']) del (row['reserve']) if not row.get('sat_num', ''): row.update({"sat_num": 0}) row['lon'] = float(row['lon']) row['lat'] = float(row['lat']) sended, status = self.retranslator.send(self.send, row, self.settings, self.ip, int(self.port)) if sended: msg = "Запись ОТПРАВЛЕНА\n" else: msg = "Запись НЕ ОТПРАВЛЕНА\n" msg += "Сервер".ljust(26, '-') + f"{self.ip}:" + f"{self.port}\n" msg += "Ретранслятор".ljust( 26, '-') + f"{self.retranslator.protocol_name}\n" msg += "ID записи".ljust(26, '-') + f"{row['id']}\n" msg += "imei".ljust(26, '-') + f"{row['imei']}\n" msg += "Время точки".ljust( 26, '-') + f"{datetime.fromtimestamp(row['datetime'])}\n" msg += "Статус отправки".ljust(26, '-') + f"{status}\n" msg += f"Записей для {self.imei}".ljust( 30, '-') + f"{self.queue.qsize()}\n" if not sended: logger.error(msg) else: logger.info(msg) condition = f" WHERE `ip`='{self.ip}' AND `port`={self.port} AND `imei`={row['imei']}" query = f"SELECT * FROM `sent_id`" + condition with self.dbconn.cursor() as cursor: cursor.execute(query) if cursor.rowcount == 0: query = f"INSERT INTO `sent_id` VALUES ({row['id']}, '{self.ip}', {self.port}, {row['imei']})" else: query = f"UPDATE `sent_id` SET `id`={row['id']}" + condition cursor.execute(query) self.dbconn.commit() self.queue.task_done()
def data_main(self, packet): packet, _ = extract_ushort(packet, '=') packet, size = extract_ubyte(packet, '=') if size == 0x84: try: logger.debug( f'[ADM{self.model}] {self.imei} принят ответ на команду {packet}' ) result = self.handle_command(packet) except Exception as e: result = "Ошибка на сервере: " + str(e) resp = {"action": "response", "result": result} self.command_response = dumps(resp) logger.debug( f'[ADM{self.model}] {self.imei} ошибка распаковки ответа на команду\n{result}\n' ) logger.info(str(e)) else: resp = {"action": "response", "result": result} self.command_response = dumps(resp) logger.debug( f'[ADM{self.model}] {self.imei} ответ на команду принят\n{result}\n' ) return None, None packet, typ = extract_ubyte(packet, '=') packet, _ = extract_ubyte(packet, '=') packet, ID = extract_ushort(packet, '=') packet, status = extract_ushort(packet, '=') packet, lat = extract_float(packet, '<') packet, lon = extract_float(packet, '<') packet, direction = extract_ushort(packet, '=') packet, speed = extract_ushort(packet, '=') packet, ACC = extract_ubyte(packet, '=') packet, HEIGHT = extract_ushort(packet, '=') packet, HDOP = extract_ubyte(packet, '=') packet, SAT_N = extract_ubyte(packet, '=') packet, timestamp = extract_uint(packet, '=') packet, V_POWER = extract_ushort(packet, '=') packet, V_BATTERY = extract_ushort(packet, '=') direction /= 10 speed /= 10 ACC /= 10 if direction > 360: direction = 0 else: direction = (direction / 2) % 0xff SAT_N = (SAT_N & 0x0f) + ((SAT_N & 0xf0) >> 4) dt = datetime.datetime.utcfromtimestamp(timestamp) data = { key: value for key, value in locals().items() if key not in ['self', 'packet'] } return packet, data
async def handler(ws, path): while True: try: rec = await ws.recv() try: rec = loads(rec) except Exception as e: logger.error(f'WEBSOCKET неизвестный пакет: {rec} {e}\n') continue if rec['action']=='command': teltonika = Teltonika.Teltonika.get_tracker(rec['imei']) adm = ADM.ADM.get_tracker(rec['imei']) ion = ION.ION.get_tracker(rec['imei']) wialoncombine = WialonCombine.WialonCombine.get_tracker(rec['imei']) if any([teltonika, adm, ion, wialoncombine]): command_response = dumps({}) logger.debug(f"WEBSOCKET tracker {rec['imei']} found") if teltonika: teltonika.command_response = {} teltonika.send_command(int(rec['codec']), rec['command']) for _ in range(30): sleep(0.5) if teltonika.command_response!={}: command_response = teltonika.command_response break elif adm: adm.command_response = {} adm.send_command(rec['command']) for _ in range(30): sleep(0.5) if adm.command_response!={}: command_response = adm.command_response break elif ion: ion.command_response = {} ion.send_command(rec['command']) for _ in range(30): sleep(0.5) if ion.command_response!={}: command_response = ion.command_response break elif wialoncombine: wialoncombine.command_response = {} wialoncombine.send_command(rec['command']) for _ in range(30): sleep(0.5) if wialoncombine.command_response!={}: command_response = wialoncombine.command_response break if command_response!={}: logger.debug(f'WEBSOCKET command response\n{command_response}') try: await ws.send(command_response) except Exception as e: logger.error(f"WEBSOCKET ошибка при отправке ответа {e}") else: await ws.send(dumps({"action":"response", "result": "Время ожидания ответа истекло"})) else: await ws.send(dumps({"action":"response", "result": "Трекер не подключен"})) logger.info(f"WEBSOCKET {rec['imei']} не подключен") continue else: continue except Exception as e: raise e
def handle_packet(self): if self.stop: self.stop = False while not self.stop: try: packet = binascii.hexlify(self.sock.recv(4096)) except Exception as e: raise e if len(packet) == 0: continue logger.debug(f'[ION] получен пакет {packet}') packet, packet_type = extract_ubyte(packet) packets = None if packet_type == 0xe7 or packet_type == 0x83: packet, packets = extract_ubyte(packet) elif packet_type == 0xf0 or packet_type == 0xf1: result = self.handle_command(packet, packet_type) resp = {"action": "response", "result": result} self.command_response = dumps(resp) if not self.imei: first_time = True else: first_time = False packet, self.imei = ION.parse_imei(packet) if first_time: logger.info( f'ION {self.imei} подключен [{self.addr[0]}:{self.addr[1]}]' ) self.assign = get_configuration(self.NAME, self.imei) self.ign_v = get_ignition_v(self.imei) logger.debug(f'[ION] {self.imei} всего записей: {packets}') all_data = [] if packets: for i in range(packets): try: packet, data = ION.parse_data(packet) logger.debug(f'[ION] {self.imei} данные #{i} {data}') data = self.rename_data(data) logger.debug( f'[ION] {self.imei} данные после переименования: {data}' ) data = self.prepare_geo(data) logger.debug( f'[ION] {self.imei} данные после обработки: {data}' ) all_data.append(data) except Exception as e: logger.error( f'[ION] {self.imei} ошибка парсинга\n{str(e)}\nПакет {packet}' ) break else: while len(packet) > 0: try: packet, data = ION.parse_data(packet) logger.debug(f'[ION] {self.imei} данные #{i} {data}') data = self.rename_data(data) logger.debug( f'[ION] {self.imei} данные после переименования: {data}' ) data = self.prepare_geo(data) logger.debug( f'[ION] {self.imei} данные после обработки: {data}' ) all_data.append(data) except Exception as e: logger.error( f'[ION] {self.imei} ошибка парсинга\n{str(e)}\nПакет {packet}' ) break count = insert_geo(all_data) logger.info(f'ION {self.imei} принято {count}/{packets} записей') if packet_type == 0x82 or packet_type == 0x83: self.sock.send(b'0')
def handle_packet(self): while not self.stop: try: packet = binascii.hexlify(self.sock.recv(4096)) except Exception: self.sock.close() self.stop = True Teltonika.TRACKERS.remove(self) logger.debug( f'[Teltonika{self.model}] {self.imei} отключен [{self.addr[0]}:{self.addr[1]}]' ) break self.lock.acquire() if len(packet) < 8: if packet == b'\xff' or packet == b'' or packet == b'ff': continue else: logger.error(f'[Teltonika] непонятный пакет: {packet}') self.sock.close() self.stop = True Teltonika.TRACKERS.remove(self) logger.debug( f'[Teltonika{self.model}] {self.imei} отключен [{self.addr[0]}:{self.addr[1]}]' ) break logger.debug(f'[Teltonika] получен пакет:\n{packet}\n') try: packet, z = extract_int(packet) #preamble zero bytes assert z == 0, 'Not teltonika packet' packet, data_len = extract_uint(packet) packet, self.codec = extract_ubyte(packet) packet, self.count = extract_ubyte(packet) logger.debug( f'[Teltonika] codec={self.codec} rec_count={self.count}\n') except Exception as e: with open('tracker_receiver/src/logs/errors.log', 'a') as fd: fd.write(f'Ошибка в распаковке {packet}\n{e}\n') if self.codec in (8, 142, 16): self.data = self.handle_data(packet) self.data = prepare_geo(self.data) count = insert_geo(self.data) logger.info( f'Teltonika{self.model} {self.imei} принято {count}/{len(self.data)} записей' ) self.sock.send(struct.pack("!I", count)) elif self.codec in (12, 13, 14): result = self.handle_command(packet) resp = {"action": "response", "result": result} resp = dumps(resp) self.command_response = resp logger.debug( f'[Teltonika] ответ на команду принят\n{result}\n') else: logger.critical(f"Teltonika неизвестный кодек {self.codec}") raise ValueError('Unknown codec') self.lock.release() sleep(2) del (self)
def handle_packet(self): if self.stop: self.stop = False self.assign = None while not self.stop: try: packet = binascii.hexlify(self.sock.recv(2**17)) self.success = True except Exception: self.sock.close() self.db.close() self.stop = True self.success = False WialonCombine.TRACKERS.remove(self) logger.debug( f'[WialonCombine] отключен [{self.addr[0]}:{self.addr[1]}]' ) break logger.debug(f'[WialonCombine] получен пакет:\n{packet}\n') count = 0 command = False packet, packet_header = self.handle_header(packet) if packet_header['type'] == 0: try: self.handle_login(packet) except: logger.error(f'[WialonCombine] unknown packet\n') continue logger.debug(f'[WialonCombine] imei:\n{self.imei}\n') elif packet_header['type'] == 1: self.assign = get_configuration(self.NAME, self.imei, self.model) while len(packet) > 4: try: packet, packet_data, packet_reserve = self.handle_data( packet) except Exception as e: logger.debug( f'[WialonCombine] error parsing {packet} {str(e)}\n' ) break if packet_reserve.get('DRIVERMESSAGE'): command = True else: command = False if not packet_data and packet_reserve: packet_data.append({ "lat": 0, "lon": 0, "timestamp": int(time()), "speed": 0, "direction": 0, }) for data in packet_data: self.data, _ = self.prepare_data(packet_reserve, data) c = insert_geo([self.data]) count += 1 elif packet_header['type'] == 2: continue else: logger.debug( f"[WialonCombine] unknown type {packet} {packet_header['type']}\n" ) self.success = False if self.success: resp = '' resp = add_short(resp, 0x4040, '>') if not command: resp = add_byte(resp, 0x00, '>') else: resp = add_byte(resp, 255, '>') resp = add_ushort(resp, self.pid, '>') logger.debug( f'[WialonCombine] {self.imei} response to tracker:\n{resp}\n' ) resp = pack(resp) self.sock.send(resp) if count: logger.info( f"WialonCombine {self.imei} принято {count} записи") else: resp = '' resp = add_short(resp, 0x4040, '>') resp = add_byte(resp, 0x03, '>') resp = add_ushort(resp, self.pid, '>') resp = pack(resp) self.sock.send(resp) logger.warning( f"WialonCombine {self.imei} пакет не был принят")