from os import getenv import ipaddress import wifi import socketpool import time import random random.seed(time.time()) random.random() class NetworkHandler: def __init__(self, sensor_class, listen_max_buffer, listen_timeout, listen_port, send_timeout, send_port): self._sensor_class = sensor_class print(self._sensor_class) self._wifi_connected = False self._listen_socket = None self._listen_max_buffer = listen_max_buffer self._listen_timeout = listen_timeout self._listen_port = listen_port self._listen_buffer = bytearray(listen_max_buffer) self._pool = None self._host_addr = '' self._listen_port = listen_port self._send_addr = '' self._send_port = send_port self._send_socket = None self._send_timeout = send_timeout self._ssid = '' def initialize(self): self._connect_wifi() while not self._wifi_connected: time.sleep(15) self._connect_wifi() print('WiFi connected -', self._ssid) self._pool = socketpool.SocketPool(wifi.radio) self._host_addr = str(wifi.radio.ipv4_address) print(self._host_addr) self._setup_listen_socket() print(f'Send addr: "{self._send_addr}"') while len(self._send_addr) == 0: print('Trying to connect to CarOS host', time.time()) if self._receive_udp(): break time.sleep(random.randint(1, 10) / 10) def update(self, utc, timer): if self._receive_udp(): timer.reset(utc) timer.set_interval(10) if not timer.check_timer(utc): return if self._send_socket: self._send_socket.close() self._send_socket = None self._send_addr = None def send(self, message): if self._send_addr is None or self._send_socket is None: return buffer = bytearray(message) ck_a, ck_b = self._calculate_checksum(buffer) buffer[-2] = ck_a buffer[-1] = ck_b try: self._send_socket.sendto(buffer, (self._send_addr, self._send_port)) except Exception as e: print("Error while sending data to: '", self._send_addr, "'", self._send_port) print(e) def _send_peer_request(self): print("Send peer request") message = bytearray(b'\xd4\x53\x6E\x77\x00') message[-1] = self._sensor_class message += '\x00' + '\x00' self.send(message) def _calculate_checksum(self, packet): ck_a = 0 ck_b = 0 for i in range(2, len(packet) - 2): ck_a += packet[i] ck_b += ck_a return [ck_a % 0x100, ck_b % 0x100] def _connect_wifi(self): self._ssid = getenv("CIRCUITPY_WIFI_SSID") print(f'Trying to connect to "{self._ssid}"') password = getenv("CIRCUITPY_WIFI_PASSWORD") try: wifi.radio.connect(self._ssid, password) self._wifi_connected = True except Exception as e: print("Could not find WiFi info. Check your settings.toml file!") self._wifi_connected = False def _setup_listen_socket(self): self._listen_socket = self._pool.socket(self._pool.AF_INET, self._pool.SOCK_DGRAM) self._listen_socket.settimeout(self._listen_timeout) self._listen_socket.bind((self._host_addr, self._listen_port)) def _setup_send_socket(self): self._send_socket = self._pool.socket(self._pool.AF_INET, self._pool.SOCK_DGRAM) self._send_socket.settimeout(self._send_timeout) def _receive_udp(self): send_addr = None try: size, addr = self._listen_socket.recvfrom_into(self._listen_buffer) data = self._listen_buffer[:size].decode('utf-8') send_addr, time_str = data.split('|') print('Data received:', data) except OSError: return False if send_addr is None: return False if send_addr != self._send_addr: self._send_addr = send_addr if self._send_socket: self._send_socket.close() self._setup_send_socket() self._send_peer_request() return True