#!/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