示例#1
0
class CameraController:
    def __init__(self):
        self.em = EventsManager()
        self.camera = Camera()
        self.ID = "Rpi-Fox-camera"
        self.info = {"info": "dummy"}
        self.commandQueue = []
        self.run()

        self.em.subscribe("%s/command" % self.ID, self.sendCommand)
        self.em.subscribe("%s/info-request" % self.ID, self.getInfo)
        self.em.publish("component-added", {"componentID": self.ID})

    def getInfo(self, message):
        self.em.publish("%s/info" % self.ID, {"info": self.info})

    def getFrame(self):
        return self.camera.get_frame()

    def saveFrameToFile(self, file):
        my_file = open(file, 'wb')
        my_file.write(self.getFrame())
        my_file.close()
        print("Image saved successfully to", file)

    def sendCommand(self, message):
        self.commandQueue.append(message)

    def _processCommandQueue(self):
        while True:
            if len(self.commandQueue) > 0:
                item = self.commandQueue.pop(0)
                command = item["command"]
                params = item["params"]
                if command == "take-photo":
                    file = "/home/pi/IotBox/files/%s" % params['name']
                    self.saveFrameToFile(file)
                elif command == "timelapse":
                    name = params['name']
                    number = params['number']
                    seconds_delay = params['seconds_delay']

                    #make folder 'output' to hold images
                    folder = "/home/pi/IotBox/files/%s" % name
                    print("Timelapse images stored in %s" % folder)
                    if not os.path.exists(folder):
                        os.makedirs(folder)

                    for x in range(0, number):
                        print("TODO: Taking photo number %d" % x)
                        self.saveFrameToFile("{}/image_{}.jpg".format(
                            folder, x))
                        sleep(seconds_delay)
                    print("Timelapse complete!")
                else:
                    print("Unknown command!")

    def run(self):
        t = threading.Thread(target=self._processCommandQueue)
        t.start()
class RhizoDeviceManager():
    def __init__(self):
        self.em = EventsManager()
        self.connectedDevices = {}  #dict of port:device

        self.em.subscribe("usb-connect", self.connectionEventHandler)
        self.em.subscribe("usb-disconnect", self.connectionEventHandler)

    def connectionEventHandler(self, event):
        type = event["topic"]
        port = event["port"]
        if (type == "usb-connect"):
            self.addDevice(port)
        elif (type == "usb-disconnect"):
            self.removeDevice(port)

    def addDevice(self, port):
        print("DeviceManager: Creating new device.")
        device = RhizoDevice(port)
        self.connectedDevices[port] = device
        self.em.publish("device-added", {"port": port})

    def removeDevice(self, port):
        print("DeviceManager: Removing device.")
        device = self.connectedDevices.pop(port)
        device.destroy()
        self.em.publish("device-removed", {})

    def getComponentIDsList(self):
        list = []
        for port in self.connectedDevices:
            device = self.connectedDevices[port]
            for componentID in device.getComponentIDsList():
                list.append(componentID)
        return list
示例#3
0
class Component():
    def __init__(self, id):
        self.id = id
        self.info = {}
        self.em = EventsManager()
        self.em.subscribe("%s/info-request" % self.id, self.getInfo)

    def getInfo(self, message):
        self.em.publish("%s/info" % self.id, {"info": self.info})

    def updateInfo(self, key, value):
        self.info[key] = value
        if key == "state":
            self.em.publish("%s/update" % self.id, {"value": value})
示例#4
0
class USBPortWatcher():
    def __init__(self):
        self.em = EventsManager()
        self.connectedUSBPorts = []
        self.watchUSB()

    def getUSBPorts(self):
        return self.connectedUSBPorts

    def _watchUSB(self):
        prev_usb_ports = []
        while True:

            # get list of usb ports with connections
            if os.path.exists('/dev/'):
                all_ports = os.listdir('/dev')
            else:
                all_ports = []
            usb_ports = [
                port_name for port_name in all_ports
                if (port_name.startswith('ttyUSB')
                    or port_name.startswith('ttyACM'))
            ]

            # look for new usb connections
            for short_port_name in usb_ports:
                if not short_port_name in prev_usb_ports:
                    port = '/dev/' + short_port_name
                    print("USBWatcher: New device found on port", port)
                    self.em.publish("usb-connect", {"port": port})

            # look for usb disconnections
            for short_port_name in prev_usb_ports:
                if not short_port_name in usb_ports:
                    port = '/dev/' + short_port_name
                    print("USBWatcher: Device removed from port", port)
                    self.em.publish("usb-disconnect", {"port": port})

            # save list for next pass around
            prev_usb_ports = usb_ports
            self.connectedUSBPorts = usb_ports
            sleep(.2)

    def watchUSB(self):
        t = threading.Thread(target=self._watchUSB)
        t.start()
示例#5
0
class IoTInterface():
    def __init__(self, componentID, mqttProvider):
        self.componentID = componentID
        self.mqtt = mqttProvider
        self.em = EventsManager()

        #subscribe to external/MQTT events to send in
        self.mqtt.subscribe("roll-call/who-there", self.announce)

        #receive commands addressed to this component
        topic = "%s/command" % self.componentID
        self.mqtt.subscribe(topic, self.processIncomingMessage)

        #subscribe to internal updates to send out
        topic = "%s/update" % self.componentID
        self.em.subscribe(topic, self.processOutgoingMessage)

        #subscribe to internal info to send out
        topic = "%s/info" % self.componentID
        self.em.subscribe(topic, self.processOutgoingMessage)

        #announce yourself
        msg = {"name": self.componentID}
        self.mqtt.publish("roll-call/hello", msg)

        #tell device to send its info
        self.em.publish("%s/info-request" % self.componentID, {})

    def destroy(self):
        #unsubscribe before I get destroyed.
        self.em.unsubscribe(self.processOutgoingMessage)

        msg = {"name": self.componentID}
        self.mqtt.publish("roll-call/goodbye", msg)
        self.mqtt.unsubscribe(self.announce)
        self.mqtt.unsubscribe(self.processIncomingMessage)

    def announce(self, message):
        msg = {"name": self.componentID}
        self.mqtt.publish("roll-call/response", msg)
        self.em.publish("%s/info-request" % self.componentID, {})

    def processOutgoingMessage(self, message):
        topic = message.pop(
            "topic")  #Separate the message and topic to format for MQTT server
        self.mqtt.publish(topic, message)

    def processIncomingMessage(self, message):
        topic = message.pop("topic")
        self.em.publish(topic, message)

        #acknowledge
        topic = "%s/response" % message["topic"]
        msg = {"response": "ack"}
        self.mqtt.publish(topic, msg)
示例#6
0
class RhizoDevice():
    def __init__(self, port):
        print("Device: Initializing myself as a new device on port %s..." %
              port)
        self.port = port
        self.em = EventsManager()
        self.components = {}  #Dict componentID:component

        self.abort = False
        self.deviceMessageQueue = []
        self.serialConnection = SerialConnection(port, self.addToMessageQueue)
        self.processMessageQueue()

        self.sendCommand({
            "command": "devices",
            "params": None
        })  #request info about what components are on the device
        self.sendCommand({
            "command": "interval",
            "params": 2
        })  #sets the data-sending rate to 1 second
        print("Device: Done Initializing.")

    def destroy(self):
        for componentID in self.components:
            self.em.unsubscribe(self.sendCommand)
            self.em.publish("component-removed", {"componentID": componentID})
        self.serialConnection.closeConnection()
        self.serialConnection = False
        self.abort = True

    def addComponent(self, component_name):
        componentID = "%s/%s" % (self.port, component_name)
        if not componentID in self.components:
            self.components[componentID] = Component(componentID)
            self.em.publish("component-added", {"componentID": componentID})
            self.em.subscribe("%s/command" % componentID, self.sendCommand)
        self.sendCommand({
            "command": "%s: info" % component_name,
            "params": None
        })  #request info about this component

    def updateComponents(self, component_name, key, value):
        componentID = "%s/%s" % (self.port, component_name)
        if componentID in self.components:
            self.components[componentID].updateInfo(key, value)
        else:
            self.addComponent(component_name)

    #messaging related methods
    def sendCommand(self, message):
        command = message["command"]
        params = message["params"]
        try:
            if params is not None:
                msg = "%s %s" % (command, params)
                self.serialConnection.writeMessage(msg)
            else:
                msg = command
                self.serialConnection.writeMessage(msg)
        except:
            print("Device: Error sending command over serial connection.")

    # collect messages from the SerialConnection
    def addToMessageQueue(self, message):
        self.deviceMessageQueue.append(message)

    # process incoming serial message queue
    def _processMessageQueue(self):
        while True:
            if not self.abort:
                if len(self.deviceMessageQueue) > 0:
                    msg = self.deviceMessageQueue.pop(0)
                    msg_array = msg.decode('utf-8').split("|")[0].split(
                        " "
                    )  # Ugly, but this is just how the messages seem to be formatted: "c:v 492|69100"
                    cmd = msg_array.pop(0).split(":")

                    #Decide what kind of message it was-- either meta:devices [components], or componentId:info_type [value]
                    if cmd[0] == "meta":
                        if cmd[1] == "devices":
                            for component in msg_array:
                                self.addComponent(component)
                    else:
                        if cmd[0] == "nack":
                            print("Device not acknowledging messages")
                            pass
                        if len(cmd) > 1:
                            if cmd[1] == "nack" or cmd[1] == "ack":
                                pass
                            else:
                                comp = cmd[0]
                                key = cmd[1]
                                value = msg_array
                                if key == "v":
                                    key = "state"
                                self.updateComponents(comp, key, value)
                else:
                    pass
            else:
                break

    def processMessageQueue(self):
        t = threading.Thread(target=self._processMessageQueue)
        t.start()