Changeset - 72dd61ca5365
[Not reviewed]
refactor
0 0 4
matthewreed - 8 years ago 2017-04-04 20:54:23

Started refactoring with the networking and modules
4 files changed with 250 insertions and 0 deletions:
0 comments (0 inline, 0 general)
message.py
Show inline comments
 
new file 100644
 
#!/usr/bin/env python
 

	
 
class HydroBotMessage:
 
    
 
    def __init__(self, module_uuid, message_type, data_key, sensor_num, data):
 
        
 
        self.module_uuid = module_uuid
 
        self.message_type = message_type
 
        self.data_key = data_key
 
        self.sensor_num = sensor_num
 
        self.data = data
 
        
 
    def __str__(self):
 
        return "Module UUID: " + str(self.module_uuid) + " Message Type: " + hex(self.message_type) + " Data Key: " + hex(self.data_key) + " Sensor Num: " + str(self.sensor_num) + " Data: " + str(self.data)
 
    
module.py
Show inline comments
 
new file 100644
 
from abc import ABCMeta, abstractmethod
 
import uuid
 

	
 
class ModuleList():
 
    
 
    def __init__(self):
 
        self._modules = []
 
        
 
    def add_module(self, module):
 
        assert isinstance(module, Module), 'invalid module'
 
        if module in self._modules:
 
            raise ValueError('Module %s already in database' % module)
 
        else:
 
            self._modules.append(module)
 
            
 
    def remove_module(self, module):
 
        assert isinstance(Module, module), 'invalid module'
 
        try:
 
            self._module.remove(module)
 
        except ValueError:
 
            raise ValueError('Module %s is not in database' % module)
 
        
 
    def lookup_module(self, uuid):
 
        for module in self._modules:
 
            if module.uuid == uuid:
 
                return module
 
            
 
    def new_module(self, device_type, address, interface):
 
        
 
        if device_type == 0x01:
 
            module = AirSenseModule(device_type, address, interface)
 
        elif device_type == 0x02:
 
            module = RelayDriveModule(device_type, address, interface)
 
        else:
 
            module = UnknownModule(device_type, address, interface)
 
        
 
        self.add_module(module)
 
        
 
        return module
 

	
 
class Module(metaclass=ABCMeta):
 

	
 
    def __init__(self, device_type, address, interface):
 
        self.device_type = device_type
 
        self.address = address
 
        self.interface = interface
 
        
 
        self.uuid = uuid.uuid1()
 
        print("Created new module! " + str(self.uuid))
 
    
 
    @abstractmethod
 
    def send_message(self):
 
        pass
 
    
 
    @abstractmethod
 
    def receive_message(self):
 
        pass
 

	
 
class AirSenseModule(Module):
 
    
 
    def __init__(self, device_type, address, interface):
 
        super(AirSenseModule, self).__init__(device_type, address, interface)
 
    
 
    def send_message(self):
 
        message = None
 
        self.interface.network.send_message(message)
 
    
 
    def receive_message(self):
 
        print("AirSenseModule receive message!")
 

	
 
class RelayDriveModule(Module):
 
    
 
    def __init__(self, device_type, address, interface):
 
        super(RelayDriveModule, self).__init__(device_type, address, interface)
 
    
 
    def send_message(self):
 
        pass
 
    
 
    def receive_message(self):
 
        print("RelayDriveModule receive message!")
 

	
 
class UnknownModule(Module):
 
    
 
    def __init__(self, device_type, address, interface):
 
        super(UnknownModule, self).__init__(device_type, address, interface)
 
    
 
    def send_message(self):
 
        pass
 
    
 
    def receive_message(self):
 
        print("UnknownModule receive message!")
 
        
network.py
Show inline comments
 
new file 100644
 
#!/usr/bin/env python
 

	
 
import network_interface
 
import module
 

	
 
class Network():
 
    
 
    def __init__(self, logger):
 
        self.interfaces = []
 
        self.module_list = module.ModuleList()
 
        self.logger = logger
 
        
 
    def add_interface(self, interface):
 
        self.interfaces.append(interface)
 
        
 
    def load_interfaces(self):
 
        #TODO: Load interfaces from config file
 
        pass
 
    
 
    def get_interface(self, interface_name):
 
        for interface in self.interfaces:
 
            if interface.interface_name == interface_name:
 
                return interface
 
    
 
    def start_interface(self, interface_name):
 
        print("Network: start interface " + interface_name)
 
        #TODO: Start interface
 
        for interface in self.interfaces:
 
            if interface.interface_name == interface_name:
 
                interface.start()
 
    
 
    def start_all_interfaces(self):
 
        print("Network: start all interfaces")
 
        for interface in self.interfaces:
 
            interface.start()
 
    
 
    def send_message(self, message):
 
        module = self.module_list.lookup_module(message.module_uuid)
 
        if not module == None:
 
            module.interface.send_message(message)
 
        else:
 
            print("Could not find module " + str(message.module_uuid))
 
    
 
    def process_message(self, message):
 
        print("Network: process message")
 
        self.module_list.lookup_module(message.module_uuid).receive_message()
 
    
network_interface.py
Show inline comments
 
new file 100644
 
#!/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
 

	
0 comments (0 inline, 0 general)