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 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 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()
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_io(self, packet): data = {} for extract_func in [ extract_byte, extract_short, extract_int, extract_longlong ]: if self.codec == 8 or self.codec == 16: packet, count = extract_ubyte(packet) elif self.codec == 142: packet, count = extract_ushort(packet) else: logger.critical(f"Teltonika неизвестный кодек {self.codec}\n") raise ValueError('Unknown codec') iodata = {} for _ in range(count): if self.codec == 8: packet, io_id = extract_ubyte(packet) elif self.codec == 142 or self.codec == 16: packet, io_id = extract_ushort(packet) else: logger.critical( f"Teltonika неизвестный кодек {self.codec}\n") raise ValueError('Unknown codec') packet, io_val = extract_func(packet) if str(io_id) not in self.decoder.keys(): logger.error( f'[Teltonika] Неизвестный AVL IO ID {io_id}\n') else: if str(io_id) in self.assign.keys(): ikey = self.assign[str(io_id)] if '*' in ikey: spl = ikey.split('*') ikey, k = spl[0], spl[1] io_val = round(io_val * float(k), 4) iodata.update({ikey: io_val}) elif self.decoder[str(io_id)] in self.assign.keys(): ikey = self.assign[self.decoder[str(io_id)]] if '*' in ikey: spl = ikey.split('*') ikey, k = spl[0], spl[1] io_val = round(io_val * float(k), 4) iodata.update({ikey: io_val}) else: iodata.update({self.decoder[str(io_id)]: io_val}) data.update(iodata) if self.codec == 142: packet, count = extract_ushort(packet) iodata = {} for _ in range(count): packet, io_id = extract_ushort(packet) packet, length = extract_ushort(packet) if length > 8: packet, io_val = extract(packet, length) else: packet, io_val = extract_x(packet, 'q', length) if str(io_id) not in self.decoder.keys(): logger.error( f'[Teltonika] Неизвестный AVL IO ID {io_id}\n') else: if str(io_id) in self.assign.keys(): ikey = self.assign[str(io_id)] if '*' in ikey: spl = ikey.split('*') ikey, k = spl[0], spl[1] io_val = round(io_val * float(k), 4) iodata.update({ikey: io_val}) elif self.decoder[str(io_id)] in self.assign.keys(): ikey = self.assign[self.decoder[str(io_id)]] if '*' in ikey: spl = ikey.split('*') ikey, k = spl[0], spl[1] io_val = round(io_val * float(k), 4) iodata.update({ikey: io_val}) else: iodata.update({self.decoder[str(io_id)]: io_val}) data.update(iodata) return packet, data
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} пакет не был принят")
def handle_data(self, packet): packet, timestamp = extract_uint(packet, '>') packet, count = extract_ubyte(packet, '>') logger.debug('timestamp ' + str(timestamp)) logger.debug('count ' + str(count)) packet_data = [] packet_reserve = {} for _ in range(count): logger.debug('packet ' + str(packet)) logger.debug('packet data ' + str(packet_data)) logger.debug('packet reserve ' + str(packet_reserve)) packet, type = extract_ubyte(packet, '>') logger.debug('type ' + str(type)) type = int(type) if type == 0: packet, count = self.get_extended_value_ushort(packet) for _ in range(count): logger.debug(f'custom {packet}') packet, name, value = self.handle_custom_param(packet) packet_reserve[name] = value elif type == 1: packet, data = self.handle_pos(packet) data['timestamp'] = timestamp packet_data.append(data) elif type == 2: packet, data = self.handle_io(packet) packet_reserve.update(data) elif type == 4: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, data = self.handle_lbs(packet) packet_reserve.update(data) elif type == 5: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, uid, value = self.handle_param(packet) packet_reserve[f'FUEL{uid}'] = value elif type == 6: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, uid, value = self.handle_param(packet) packet_reserve[f'TEMP{uid}'] = value elif type == 7: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, uid, value = self.handle_param(packet) packet_reserve[f'CAN{uid}'] = value elif type == 8: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, uid, value = self.handle_param(packet) packet_reserve[f'COUNTER{uid}'] = value elif type == 9: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, uid, value = self.handle_param(packet) packet_reserve[f'ADC{uid}'] = value elif type == 10: packet, count = extract_ubyte(packet, '>') for _ in range(count): packet, uid, value = self.handle_param(packet) packet_reserve[f'DRIVER{uid}'] = value elif type == 12: packet, msg = extract_str(packet, (len(packet) - 6) // 2, '!') msg = msg.decode() resp = {"action": "response", "result": msg} self.command_response = dumps(resp) packet_reserve[f'DRIVERMESSAGE'] = msg else: logger.error(f'[WialonCombine] idk') self.success = False break logger.debug( f'[WialonCombine] main data: {packet_data} [{packet_reserve}]') return packet, packet_data, packet_reserve