from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend import os import sys import socket import datetime import struct from crccheck.crc import Crc16, CrcArc import binascii class StringMaker: def __init__(self): pass def send_alarm(self, alarm_command, user_id, output_coordinates, key, host, port): key = bytes.fromhex(key) now = datetime.datetime.now() date_part = now.strftime("%m-%d-%Y") time_part = now.strftime("%H:%M:%S") input_string = f'"*SIA-DCS"0005L0#{user_id}[#{user_id}|{alarm_command}]{output_coordinates}_{time_part},{date_part}' print(f"Input String: {input_string}") part_before, part_after = input_string.split('[', 1) part_before = f"{part_before}[" part_after = "|" + part_after encryption_part = self.add_padding(part_after) print(f"Padded Input: {encryption_part}") encrypted_hex = self.encrypt(encryption_part, key) print(f"Encrypted Hex: {encrypted_hex}") before_and_after = f"{part_before}{encrypted_hex}" crc_hash = self.calculate_crc(before_and_after.encode()) with_hash = f"{crc_hash}{before_and_after}" with_line_feed_and_return = f"\u000A{with_hash}\u000D" message_bytes = with_line_feed_and_return.encode() tcp_response = self.send_bytes_with_tcp(host, port, message_bytes) return tcp_response.decode() if tcp_response is not None else "No data from Patriot" def to_ascii_hex(self, byte_array): return byte_array.hex() def add_padding(self, input_string): # Convert the input string to bytes input_bytes = input_string.encode() # Calculate the pad length pad_length = 16 - len(input_bytes) % 16 pad_length = pad_length if pad_length != 16 else 0 # Generate padding with ASCII characters padding_ascii = bytes([i % 26 + 65 for i in range(pad_length)]) # Concatenate padding and input bytes padded_bytes = padding_ascii + input_bytes return padded_bytes def get_string_after_first_occurrence(self, input_string, character): index = input_string.find(character) return input_string[index + 1:] if index != -1 else "" def encrypt(self, input_bytes, key): key_bytes = key data_bytes = input_bytes # Use the same initialization vector (IV) as in your decryption function iv = b'\x00' * 16 cipher = Cipher(algorithms.AES(key_bytes), modes.CBC(iv), backend=default_backend()) encryptor = cipher.encryptor() encrypted_data = encryptor.update(data_bytes) + encryptor.finalize() return binascii.hexlify(encrypted_data).decode('ascii') def decrypt(self, input_bytes, key): cipher = Cipher(algorithms.AES(key), modes.CFB(os.urandom(16)), backend=default_backend()) decryptor = cipher.decryptor() decrypted = decryptor.update(input_bytes) + decryptor.finalize() return decrypted.decode() def send_bytes_with_tcp(self, ip_address, port, data): try: with socket.create_connection((ip_address, port), timeout=5) as client: client.sendall(data) response = client.recv(1024) return response except Exception as ex: print(f"Error: {ex}") return None def convert_to_dms_format(self, dd, direction): degrees = int(abs(dd)) minutes = (abs(dd) - degrees) * 60 seconds = (minutes - int(minutes)) * 60 sign = 'W' if dd < 0 and direction == "X" else 'S' if dd < 0 and direction == "Y" else 'E' if direction == "X" else 'N' return f"{direction}{degrees:03d}{sign}{int(minutes):02d}.{int(round(seconds * 10000000)):07d}" def calculate_crc(self, input_bytes): crc_arc = CrcArc() crc_arc.process(input_bytes) crc_value_hex = crc_arc.finalhex() return f"{crc_value_hex.upper()}{len(input_bytes):04X}" arg1 = sys.argv[1] if len(sys.argv) > 1 else None arg2 = sys.argv[2] if len(sys.argv) > 2 else None arg3 = sys.argv[3] if len(sys.argv) > 3 else None host = sys.argv[4] if len(sys.argv) > 4 else None arg5 = sys.argv[5] if len(sys.argv) > 5 else None signalType = sys.argv[6] if len(sys.argv) > 6 else "PA" zone = sys.argv[7] if len(sys.argv) > 7 else "00" arg8 = sys.argv[8] if len(sys.argv) > 8 else "mysmallkey123456" port = int(arg5) def main(): global host global port global arg1 global arg2 global arg3 global signalType global zone string_maker = StringMaker() key = arg8.encode().hex().upper() print(key) ClientID = arg1 SignalType = "Nri/" + signalType Zone = zone SignalAndZone = SignalType + Zone PosistionLat = arg3 PositionLong = arg2 def convert_coordinates(arg2, arg3): # Extract numerical values for longitude and latitude lon_value = float(arg3) lat_value = float(arg2) # Convert longitude to the desired format lon_degrees = int(lon_value) lon_minutes = (lon_value - lon_degrees) * 60 lon_format = f"[X{lon_degrees:03d}E{lon_minutes:.8f}]" # Convert latitude to the desired format lat_degrees = int(lat_value) lat_minutes = (lat_value - lat_degrees) * 60 lat_format = f"[Y{lat_degrees:02d}N{lat_minutes:.8f}]" # Combine the formatted coordinates result = lon_format + lat_format return result output_coordinates = convert_coordinates(arg2, arg3) result = string_maker.send_alarm(SignalAndZone, int(ClientID), output_coordinates, key, host, port) print(result) if __name__ == "__main__": main()