#!/usr/bin/env python import os import struct import _thread from abc import ABCMeta, abstractmethod from message import HydroBotMessage import module from canard import can from canard.hw import socketcan from canard.utils import queue class NetworkInterface(metaclass=ABCMeta): def __init__(self, network, logger): self.network = network self.logger = logger @abstractmethod def start(self): print("Network: start") @abstractmethod def send_message(self, message): pass def process_message(self, message): print("Network Interface: process message") class CanBusNetworkInterface(NetworkInterface): def __init__(self, network, interface_name, logger): super(CanBusNetworkInterface, self).__init__(network, logger) # Bring up CAN interface (maybe do this in a systemd service file) # Passing random arguments to sudo is super dangerous os.system("sudo ip link set " + interface_name + " up type can bitrate 500000") self.interface_name = interface_name self.dev = socketcan.SocketCanDev(interface_name) self.queue = queue.CanQueue(self.dev) self.address_lookup = {} self.uuid_lookup = {} def start(self): super(CanBusNetworkInterface, self).start() print("CanBusNetworkInterface: start") self.queue.start() _thread.start_new_thread(self.process_message, ()) def send_message(self, message): address = self.uuid_lookup[message.module_uuid] can_frame = can.Frame(address, 8, [message.message_type, (message.data_key>>8) & 0xff, (message.data_key>>0) & 0xff, message.sensor_num] + list(struct.pack("f", message.data))) self.logger.debug("Send CAN message! CAN ID: " + hex(can_frame.id) + " Data: " + str(can_frame.data)) self.queue.send(can_frame) def process_message(self): while True: frame = self.queue.recv() if frame != None: print("CanBusNetworkInterface: process message") if not frame.id in self.address_lookup: new_module = self.network.module_list.new_module(frame.data[0] & 0x7f, frame.id, self) self.address_lookup[frame.id] = new_module.uuid self.uuid_lookup[new_module.uuid] = frame.id self.logger.debug("Received CAN message! ID: " + hex(frame.id)) message = HydroBotMessage(self.address_lookup[frame.id], frame.data[0], ((frame.data[1] << 8) + frame.data[2]), frame.data[3], ((frame.data[4] << 24) + (frame.data[5] << 16) + (frame.data[6] << 8) + frame.data[7])) print(message) self.network.process_message(message) class WifiNetworkInterface(NetworkInterface): def __init__(self, network, logger): super(WifiNetworkInterface, self).__init__(network, logger) def start(self): pass def send_message(self, message): pass def process_message(self, message): pass #module knows how to send and recieve messages