Example #1
0
    def _handle_device_change(self, msg):
        if msg.event == MsgHubAttachedIO.EVENT_DETACHED:
            log.debug("Detaching peripheral: %s", self.peripherals[msg.port])
            self.peripherals.pop(msg.port)
            return

        assert msg.event in (msg.EVENT_ATTACHED, msg.EVENT_ATTACHED_VIRTUAL)
        port = msg.port
        dev_type = ushort(msg.payload, 0)

        if dev_type in PERIPHERAL_TYPES:
            self.peripherals[port] = PERIPHERAL_TYPES[dev_type](self, port)
        else:
            #log.warning("Have not dedicated class for peripheral type %x on port %x", dev_type, port)
            self.peripherals[port] = Peripheral(self, port)

        log.info("Attached peripheral: %s", self.peripherals[msg.port])

        if msg.event == msg.EVENT_ATTACHED:
            hw_revision = reversed([usbyte(msg.payload, x) for x in range(2, 6)])
            sw_revision = reversed([usbyte(msg.payload, x) for x in range(6, 10)])
            # what to do with this info? it's useless, I guess
            del hw_revision, sw_revision
        elif msg.event == msg.EVENT_ATTACHED_VIRTUAL:
            self.peripherals[port].virtual_ports = (usbyte(msg.payload, 2), usbyte(msg.payload, 3))
Example #2
0
    def _notify(self, handle, data):
        orig = data

        if handle != MOVE_HUB_HARDWARE_HANDLE:
            log.warning("Unsupported notification handle: 0x%s", handle)
            return

        log.debug("Notification on %s: %s", handle, str2hex(orig))

        msg_type = usbyte(data, 2)

        if msg_type == MSG_PORT_INFO:
            self._handle_port_info(data)
        elif msg_type == MSG_PORT_STATUS:
            self._handle_port_status(data)
        elif msg_type == MSG_SENSOR_DATA:
            self._handle_sensor_data(data)
        elif msg_type == MSG_SENSOR_SUBSCRIBE_ACK:
            port = usbyte(data, 3)
            log.debug("Sensor subscribe ack on port %s", PORTS[port])
            self.devices[port].finished()
        elif msg_type == MSG_PORT_CMD_ERROR:
            log.warning("Command error: %s", str2hex(data[3:]))
            port = usbyte(data, 3)
            self.devices[port].finished()
        elif msg_type == MSG_DEVICE_SHUTDOWN:
            log.warning("Device reported shutdown: %s", str2hex(data))
            raise KeyboardInterrupt("Device shutdown")
        elif msg_type == MSG_DEVICE_INFO:
            self._handle_device_info(data)
        else:
            log.warning("Unhandled msg type 0x%x: %s", msg_type, str2hex(orig))
Example #3
0
    def _handle_device_info(self, data):
        kind = usbyte(data, 3)
        if kind == 2:
            self.button.handle_port_data(data)

        if usbyte(data, 4) == 0x06:
            self.info[kind] = data[5:]
        else:
            log.warning("Unhandled device info: %s", str2hex(data))
Example #4
0
    def _handle_port_info(self, data):
        port = usbyte(data, 3)
        status = usbyte(data, 4)

        if status == self.DEV_STATUS_DETACHED:
            log.info("Detached %s", self.devices[port])
            self.devices[port] = None
        elif status == self.DEV_STATUS_DEVICE or status == self.DEV_STATUS_GROUP:
            dev_type = usbyte(data, 5)
            self._attach_device(dev_type, port)
        else:
            raise ValueError("Unhandled device status: %s", status)

        self._update_field(port)
        if self.devices[port] is None:
            del self.devices[port]
Example #5
0
    def _handle_sensor_data(self, data):
        port = usbyte(data, 3)
        if port not in self.devices:
            log.warning("Notification on port with no device: %s", PORTS[port])
            return

        device = self.devices[port]
        device.queue_port_data(data)
Example #6
0
 def _decode_port_data(self, msg):
     data = msg.payload
     if self._port_mode.mode == self.MODE_2AXIS_ANGLE:
         roll = unpack('<b', data[0:1])[0]
         pitch = unpack('<b', data[1:2])[0]
         return (roll, pitch)
     elif self._port_mode.mode == self.MODE_3AXIS_SIMPLE:
         state = usbyte(data, 0)
         return (state, )
     elif self._port_mode.mode == self.MODE_2AXIS_SIMPLE:
         state = usbyte(data, 0)
         return (state, )
     elif self._port_mode.mode == self.MODE_IMPACT_COUNT:
         bump_count = usint(data, 0)
         return (bump_count, )
     elif self._port_mode.mode == self.MODE_3AXIS_ACCEL:
         roll = unpack('<b', data[0:1])[0]
         pitch = unpack('<b', data[1:2])[0]
         yaw = unpack('<b', data[2:3])[0]  # did I get the order right?
         return (roll, pitch, yaw)
     elif self._port_mode.mode == self.MODE_ORIENT_CF:
         state = usbyte(data, 0)
         return (state, )
     elif self._port_mode.mode == self.MODE_IMPACT_CF:
         state = usbyte(data, 0)
         return (state, )
     elif self._port_mode.mode == self.MODE_CALIBRATION:
         return (usbyte(data, 0), usbyte(data, 1), usbyte(data, 2))
     else:
         log.debug("Got tilt sensor data while in unexpected mode: %r",
                   self._port_mode)
         return ()
Example #7
0
 def _get_upstream_msg(self, data):
     msg_type = usbyte(data, 2)
     msg = None
     for msg_kind in UPSTREAM_MSGS:
         if msg_type == msg_kind.TYPE:
             msg = msg_kind.decode(data)
             log.debug("Decoded message: %r", msg)
             break
     assert msg
     return msg
Example #8
0
    def _handle_port_status(self, data):
        port = usbyte(data, 3)
        status = usbyte(data, 4)

        if status == STATUS_STARTED:
            self.devices[port].started()
        elif status == STATUS_FINISHED:
            self.devices[port].finished()
        elif status == STATUS_CONFLICT:
            log.warning("Command conflict on port %s", PORTS[port])
            self.devices[port].finished()
        elif status == STATUS_INPROGRESS:
            log.warning("Another command is in progress on port %s",
                        PORTS[port])
            self.devices[port].finished()
        elif status == STATUS_INTERRUPTED:
            log.warning("Command interrupted on port %s", PORTS[port])
            self.devices[port].finished()
        else:
            log.warning("Unhandled status value: 0x%x on port %s", status,
                        PORTS[port])
Example #9
0
 def handle_port_data(self, data):
     if self._port_subscription_mode == self.SENSOR_ANGLE:
         rotation = unpack("<l", data[4:8])[0]
         self._notify_subscribers(rotation)
     elif self._port_subscription_mode == self.SENSOR_SOMETHING1:
         # TODO: understand what it means
         rotation = usbyte(data, 4)
         self._notify_subscribers(rotation)
     elif self._port_subscription_mode == self.SENSOR_SPEED:
         rotation = unpack("<b", data[4])[0]
         self._notify_subscribers(rotation)
     else:
         log.debug("Got motor sensor data while in unexpected mode: %s",
                   self._port_subscription_mode)
Example #10
0
    def _report_status(self):
        # maybe add firmware version
        name = self.send(MsgHubProperties(MsgHubProperties.ADVERTISE_NAME, MsgHubProperties.UPD_REQUEST))
        mac = self.send(MsgHubProperties(MsgHubProperties.PRIMARY_MAC, MsgHubProperties.UPD_REQUEST))
        log.info("%s on %s", name.payload, str2hex(mac.payload))

        voltage = self.send(MsgHubProperties(MsgHubProperties.VOLTAGE_PERC, MsgHubProperties.UPD_REQUEST))
        assert isinstance(voltage, MsgHubProperties)
        log.info("Voltage: %s%%", usbyte(voltage.parameters, 0))

        voltage = self.send(MsgHubAlert(MsgHubAlert.LOW_VOLTAGE, MsgHubAlert.UPD_REQUEST))
        assert isinstance(voltage, MsgHubAlert)
        if not voltage.is_ok():
            log.warning("Low voltage, check power source (maybe replace battery)")
Example #11
0
 def _decode_port_data(self, msg):
     data = msg.payload
     if self._port_mode.mode == self.SENSOR_ANGLE:
         angle = unpack("<l", data[0:4])[0]
         return (angle,)
     elif self._port_mode.mode == self.SENSOR_SOMETHING1:
         smth = usbyte(data, 0)
         return (smth,)
     elif self._port_mode.mode == self.SENSOR_SPEED:
         speed = unpack("<b", data[0])[0]
         return (speed,)
     else:
         log.debug("Got motor sensor data while in unexpected mode: %r", self._port_mode)
         return ()
Example #12
0
    def test_hub_properties(self):
        conn = ConnectionMock().connect()
        hub = Hub(conn)

        conn.notification_delayed('060001060600', 0.1)
        msg = MsgHubProperties(MsgHubProperties.VOLTAGE_PERC,
                               MsgHubProperties.UPD_REQUEST)
        resp = hub.send(msg)
        assert isinstance(resp, MsgHubProperties)
        self.assertEqual(1, len(resp.parameters))
        self.assertEqual(0, usbyte(resp.parameters, 0))

        conn.notification_delayed('12000101064c45474f204d6f766520487562', 0.1)
        msg = MsgHubProperties(MsgHubProperties.ADVERTISE_NAME,
                               MsgHubProperties.UPD_REQUEST)
        resp = hub.send(msg)
        assert isinstance(resp, MsgHubProperties)
        self.assertEqual(b"LEGO Move Hub", resp.parameters)

        conn.wait_notifications_handled()
Example #13
0
 def _decode_port_data(self, msg):
     data = msg.payload
     if self._port_mode.mode == self.COLOR_INDEX:
         color = usbyte(data, 0)
         return (color, )
     elif self._port_mode.mode == self.COLOR_DISTANCE_FLOAT:
         color = usbyte(data, 0)
         val = usbyte(data, 1)
         partial = usbyte(data, 3)
         if partial:
             val += 1.0 / partial
         return (color, float(val))
     elif self._port_mode.mode == self.DISTANCE_INCHES:
         val = usbyte(data, 0)
         return (val, )
     elif self._port_mode.mode == self.DISTANCE_REFLECTED:
         val = usbyte(data, 0) / 100.0
         return (val, )
     elif self._port_mode.mode == self.AMBIENT_LIGHT:
         val = usbyte(data, 0) / 100.0
         return (val, )
     elif self._port_mode.mode == self.COUNT_2INCH:
         count = usint(data, 0)
         return (count, )
     elif self._port_mode.mode == self.COLOR_RGB:
         val1 = int(255 * ushort(data, 0) / 1023.0)
         val2 = int(255 * ushort(data, 2) / 1023.0)
         val3 = int(255 * ushort(data, 4) / 1023.0)
         return (val1, val2, val3)
     elif self._port_mode.mode == self.DEBUG:
         val1 = 10 * ushort(data, 0) / 1023.0
         val2 = 10 * ushort(data, 2) / 1023.0
         return (val1, val2)
     elif self._port_mode.mode == self.CALIBRATE:
         return [ushort(data, x * 2) for x in range(8)]
     else:
         log.debug("Unhandled data in mode %s: %s", self._port_mode.mode,
                   str2hex(data))
         return ()
Example #14
0
 def handle_port_data(self, data):
     if self._port_subscription_mode == self.MODE_3AXIS_SIMPLE:
         state = usbyte(data, 4)
         self._notify_subscribers(state)
     elif self._port_subscription_mode == self.MODE_2AXIS_SIMPLE:
         state = usbyte(data, 4)
         self._notify_subscribers(state)
     elif self._port_subscription_mode == self.MODE_BUMP_COUNT:
         bump_count = ushort(data, 4)
         self._notify_subscribers(bump_count)
     elif self._port_subscription_mode == self.MODE_2AXIS_FULL:
         roll = self._byte2deg(usbyte(data, 4))
         pitch = self._byte2deg(usbyte(data, 5))
         self._notify_subscribers(roll, pitch)
     elif self._port_subscription_mode == self.MODE_3AXIS_FULL:
         roll = self._byte2deg(usbyte(data, 4))
         pitch = self._byte2deg(usbyte(data, 5))
         yaw = self._byte2deg(usbyte(data, 6))  # did I get the order right?
         self._notify_subscribers(roll, pitch, yaw)
     else:
         log.debug("Got tilt sensor data while in unexpected mode: %s",
                   self._port_subscription_mode)
Example #15
0
 def handle_port_data(self, data):
     if self._port_subscription_mode == self.COLOR_DISTANCE_FLOAT:
         color = usbyte(data, 4)
         distance = usbyte(data, 5)
         partial = usbyte(data, 7)
         if partial:
             distance += 1.0 / partial
         self._notify_subscribers(color, float(distance))
     elif self._port_subscription_mode == self.COLOR_ONLY:
         color = usbyte(data, 4)
         self._notify_subscribers(color)
     elif self._port_subscription_mode == self.DISTANCE_INCHES:
         distance = usbyte(data, 4)
         self._notify_subscribers(distance)
     elif self._port_subscription_mode == self.DISTANCE_HOW_CLOSE:
         distance = usbyte(data, 4)
         self._notify_subscribers(distance)
     elif self._port_subscription_mode == self.DISTANCE_SUBINCH_HOW_CLOSE:
         distance = usbyte(data, 4)
         self._notify_subscribers(distance)
     elif self._port_subscription_mode == self.OFF1 or self._port_subscription_mode == self.OFF2:
         log.info("Turned off led on %s", self)
     elif self._port_subscription_mode == self.COUNT_2INCH:
         count = unpack("<L", data[4:8])[0]  # is it all 4 bytes or just 2?
         self._notify_subscribers(count)
     elif self._port_subscription_mode == self.STREAM_3_VALUES:
         # TODO: understand better meaning of these 3 values
         val1 = ushort(data, 4)
         val2 = ushort(data, 6)
         val3 = ushort(data, 8)
         self._notify_subscribers(val1, val2, val3)
     elif self._port_subscription_mode == self.LUMINOSITY:
         luminosity = ushort(data, 4) / 1023.0
         self._notify_subscribers(luminosity)
     else:  # TODO: support whatever we forgot
         log.debug("Unhandled data in mode %s: %s",
                   self._port_subscription_mode, str2hex(data))
Example #16
0
 def _props_msg(self, msg):
     """
     :type msg: MsgHubProperties
     """
     if msg.property == MsgHubProperties.BUTTON and msg.operation == MsgHubProperties.UPSTREAM_UPDATE:
         self._notify_subscribers(usbyte(msg.parameters, 0))
Example #17
0
 def handle_port_data(self, data):
     param = usbyte(data, 5)
     if self.in_progress():
         self.finished()
     self._notify_subscribers(bool(param))
Example #18
0
 def _decode_port_data(self, msg):
     if len(msg.payload) == 3:
         return usbyte(msg.payload, 0), usbyte(msg.payload,
                                               1), usbyte(msg.payload, 2),
     else:
         return usbyte(msg.payload, 0),