Files
car-os-sensor/lib/car_os/network_handler.py
T

119 lines
4.0 KiB
Python

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
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):
if self._receive_udp():
return
def send(self, message):
if self._send_addr is None or self._send_socket is None:
print(self._send_addr, self._send_socket)
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