Exemplo n.º 1
1
class RileyLink(PacketRadio):
    def __init__(self):
        self.peripheral = None
        self.pa_level_index = PA_LEVELS.index(0x84)
        self.data_handle = None
        self.logger = getLogger()
        self.address = None
        if os.path.exists(RILEYLINK_MAC_FILE):
            with open(RILEYLINK_MAC_FILE, "r") as stream:
                self.address = stream.read()
        self.service = None
        self.response_handle = None
        self.notify_event = Event()
        self.initialized = False

    def connect(self, force_initialize=False):
        try:
            if self.address is None:
                self.address = self._findRileyLink()

            if self.peripheral is None:
                self.peripheral = Peripheral()

            try:
                state = self.peripheral.getState()
                if state == "conn":
                    return
            except BTLEException:
                pass

            self._connect_retry(3)

            self.service = self.peripheral.getServiceByUUID(RILEYLINK_SERVICE_UUID)
            data_char = self.service.getCharacteristics(RILEYLINK_DATA_CHAR_UUID)[0]
            self.data_handle = data_char.getHandle()

            char_response = self.service.getCharacteristics(RILEYLINK_RESPONSE_CHAR_UUID)[0]
            self.response_handle = char_response.getHandle()

            response_notify_handle = self.response_handle + 1
            notify_setup = b"\x01\x00"
            self.peripheral.writeCharacteristic(response_notify_handle, notify_setup)

            while self.peripheral.waitForNotifications(0.05):
                self.peripheral.readCharacteristic(self.data_handle)

            if self.initialized:
                self.init_radio(force_initialize)
            else:
                self.init_radio(True)
        except BTLEException:
            if self.peripheral is not None:
                self.disconnect()
            raise

    def disconnect(self, ignore_errors=True):
        try:
            if self.peripheral is None:
                self.logger.info("Already disconnected")
                return
            self.logger.info("Disconnecting..")
            if self.response_handle is not None:
                response_notify_handle = self.response_handle + 1
                notify_setup = b"\x00\x00"
                self.peripheral.writeCharacteristic(response_notify_handle, notify_setup)
        except BTLEException:
            if not ignore_errors:
                raise
        finally:
            try:
                if self.peripheral is not None:
                    self.peripheral.disconnect()
                    self.peripheral = None
            except BTLEException:
                if ignore_errors:
                    self.logger.exception("Ignoring btle exception during disconnect")
                else:
                    raise

    def get_info(self):
        try:
            self.connect()
            bs = self.peripheral.getServiceByUUID(XGATT_BATTERYSERVICE_UUID)
            bc = bs.getCharacteristics(XGATT_BATTERY_CHAR_UUID)[0]
            bch = bc.getHandle()
            battery_value = int(self.peripheral.readCharacteristic(bch)[0])
            self.logger.debug("Battery level read: %d", battery_value)
            version, v_major, v_minor = self._read_version()
            return { "battery_level": battery_value, "mac_address": self.address,
                    "version_string": version, "version_major": v_major, "version_minor": v_minor }
        except BTLEException as btlee:
            raise PacketRadioError("Error communicating with RileyLink") from btlee
        finally:
            self.disconnect()

    def _read_version(self):
        version = None
        try:
            if os.path.exists(RILEYLINK_VERSION_FILE):
                with open(RILEYLINK_VERSION_FILE, "r") as stream:
                    version = stream.read()
            else:
                response = self._command(Command.GET_VERSION)
                if response is not None and len(response) > 0:
                    version = response.decode("ascii")
                    self.logger.debug("RL reports version string: %s" % version)

                    try:
                        with open(RILEYLINK_VERSION_FILE, "w") as stream:
                            stream.write(version)
                    except IOError:
                        self.logger.exception("Failed to store version in file")

            if version is None:
                return "0.0", 0, 0

            try:
                m = re.search(".+([0-9]+)\\.([0-9]+)", version)
                if m is None:
                    raise PacketRadioError("Failed to parse firmware version string: %s" % version)

                v_major = int(m.group(1))
                v_minor = int(m.group(2))
                self.logger.debug("Interpreted version major: %d minor: %d" % (v_major, v_minor))

                return version, v_major, v_minor

            except Exception as ex:
                raise PacketRadioError("Failed to parse firmware version string: %s" % version) from ex

        except IOError:
            self.logger.exception("Error reading version file")
        except PacketRadioError:
            raise

        response = self._command(Command.GET_VERSION)
        if response is not None and len(response) > 0:
            version = response.decode("ascii")
            self.logger.debug("RL reports version string: %s" % version)
            try:
                m = re.search(".+([0-9]+)\\.([0-9]+)", version)
                if m is None:
                    raise PacketRadioError("Failed to parse firmware version string: %s" % version)

                v_major = int(m.group(1))
                v_minor = int(m.group(2))
                self.logger.debug("Interpreted version major: %d minor: %d" % (v_major, v_minor))

                return (version, v_major, v_minor)
            except PacketRadioError:
                raise
            except Exception as ex:
                raise PacketRadioError("Failed to parse firmware version string: %s" % version) from ex

    def init_radio(self, force_init=False):
        try:
            version, v_major, v_minor = self._read_version()

            if v_major < 2:
                self.logger.error("Firmware version is below 2.0")
                raise PacketRadioError("Unsupported RileyLink firmware %d.%d (%s)" %
                                        (v_major, v_minor, version))

            if not force_init:
                if v_major == 2 and v_minor < 3:
                    response = self._command(Command.READ_REGISTER, bytes([Register.SYNC1, 0x00]))
                else:
                    response = self._command(Command.READ_REGISTER, bytes([Register.SYNC1]))
                if response is not None and len(response) > 0 and response[0] == 0xA5:
                    return

            self._command(Command.RADIO_RESET_CONFIG)
            self._command(Command.SET_SW_ENCODING, bytes([Encoding.MANCHESTER]))
            frequency = int(433910000 / (24000000 / pow(2, 16)))
            self._command(Command.SET_PREAMBLE, bytes([0x66, 0x65]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FREQ0, frequency & 0xff]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FREQ1, (frequency >> 8) & 0xff]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FREQ2, (frequency >> 16) & 0xff]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.PKTCTRL1, 0x20]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.PKTCTRL0, 0x00]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FSCTRL1, 0x06]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.MDMCFG4, 0xCA]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.MDMCFG3, 0xBC]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.MDMCFG2, 0x06]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.MDMCFG1, 0x70]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.MDMCFG0, 0x11]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.DEVIATN, 0x44]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.MCSM0, 0x18]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FOCCFG, 0x17]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FSCAL3, 0xE9]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FSCAL2, 0x2A]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FSCAL1, 0x00]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FSCAL0, 0x1F]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.TEST1, 35]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.TEST0, 0x09]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.PATABLE0, PA_LEVELS[self.pa_level_index]]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.FREND0, 0x00]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.SYNC1, 0xA5]))
            self._command(Command.UPDATE_REGISTER, bytes([Register.SYNC0, 0x5A]))

            response = self._command(Command.GET_STATE)
            if response != b"OK":
                raise PacketRadioError("Rileylink state is not OK. Response returned: %s" % response)

            self.initialized = True

        except PacketRadioError as rle:
            self.logger.error("Error while initializing rileylink radio: %s", rle)
            raise

    def tx_up(self):
        if self.pa_level_index < len(PA_LEVELS) - 1:
            self.pa_level_index += 1
            self._set_amp(self.pa_level_index)

    def tx_down(self):
        if self.pa_level_index > 0:
            self.pa_level_index -= 1
            self._set_amp(self.pa_level_index)

    def set_tx_power(self, tx_power):
        if tx_power is None:
            return
        elif tx_power == TxPower.Lowest:
            self._set_amp(0)
        elif tx_power == TxPower.Low:
            self._set_amp(PA_LEVELS.index(0x12))
        elif tx_power == TxPower.Normal:
            self._set_amp(PA_LEVELS.index(0x60))
        elif tx_power == TxPower.High:
            self._set_amp(PA_LEVELS.index(0xC8))
        elif tx_power == TxPower.Highest:
            self._set_amp(PA_LEVELS.index(0xC0))

    def get_packet(self, timeout=5.0):
        try:
            self.connect()
            return self._command(Command.GET_PACKET, struct.pack(">BL", 0, int(timeout * 1000)),
                                 timeout=float(timeout)+0.5)
        except PacketRadioError as rle:
            self.logger.error("Error while receiving data: %s", rle)
            raise

    def send_and_receive_packet(self, packet, repeat_count, delay_ms, timeout_ms, retry_count, preamble_ext_ms):

        try:
            self.connect()
            return self._command(Command.SEND_AND_LISTEN,
                                  struct.pack(">BBHBLBH",
                                              0,
                                              repeat_count,
                                              delay_ms,
                                              0,
                                              timeout_ms,
                                              retry_count,
                                              preamble_ext_ms)
                                              + packet,
                                  timeout=30)
        except PacketRadioError as rle:
            self.logger.error("Error while sending and receiving data: %s", rle)
            raise

    def send_packet(self, packet, repeat_count, delay_ms, preamble_extension_ms):
        try:
            self.connect()
            result = self._command(Command.SEND_PACKET, struct.pack(">BBHH", 0, repeat_count, delay_ms,
                                                                   preamble_extension_ms) + packet,
                                  timeout=30)
            return result
        except PacketRadioError as rle:
            self.logger.error("Error while sending data: %s", rle)
            raise

    def _set_amp(self, index=None):
        try:
            self.connect()
            if index is not None:
                self.pa_level_index = index
            self._command(Command.UPDATE_REGISTER, bytes([Register.PATABLE0, PA_LEVELS[self.pa_level_index]]))
            self.logger.debug("Setting pa level to index %d of %d" % (self.pa_level_index, len(PA_LEVELS)))
        except PacketRadioError:
            self.logger.exception("Error while setting tx amplification")
            raise


    def _findRileyLink(self):
        scanner = Scanner()
        found = None
        self.logger.debug("Scanning for RileyLink")
        retries = 10
        while found is None and retries > 0:
            retries -= 1
            for result in scanner.scan(1.0):
                if result.getValueText(7) == RILEYLINK_SERVICE_UUID:
                    self.logger.debug("Found RileyLink")
                    found = result.addr
                    try:
                        with open(RILEYLINK_MAC_FILE, "w") as stream:
                            stream.write(result.addr)
                    except IOError:
                        self.logger.warning("Cannot store rileylink mac radio_address for later")
                    break

        if found is None:
            raise PacketRadioError("Could not find RileyLink")

        return found

    def _connect_retry(self, retries):
        while retries > 0:
            retries -= 1
            self.logger.info("Connecting to RileyLink, retries left: %d" % retries)

            try:
                self.peripheral.connect(self.address)
                self.logger.info("Connected")
                break
            except BTLEException as btlee:
                self.logger.warning("BTLE exception trying to connect: %s" % btlee)
                try:
                    p = subprocess.Popen(["ps", "-A"], stdout=subprocess.PIPE)
                    out, err = p.communicate()
                    for line in out.splitlines():
                        if "bluepy-helper" in line:
                            pid = int(line.split(None, 1)[0])
                            os.kill(pid, 9)
                            break
                except:
                    self.logger.warning("Failed to kill bluepy-helper")
                time.sleep(1)

    def _command(self, command_type, command_data=None, timeout=10.0):
        try:
            if command_data is None:
                data = bytes([1, command_type])
            else:
                data = bytes([len(command_data) + 1, command_type]) + command_data

            self.peripheral.writeCharacteristic(self.data_handle, data, withResponse=True)

            if not self.peripheral.waitForNotifications(timeout):
                raise PacketRadioError("Timed out while waiting for a response from RileyLink")

            response = self.peripheral.readCharacteristic(self.data_handle)

            if response is None or len(response) == 0:
                raise PacketRadioError("RileyLink returned no response")
            else:
                if response[0] == Response.COMMAND_SUCCESS:
                    return response[1:]
                elif response[0] == Response.COMMAND_INTERRUPTED:
                    self.logger.warning("A previous command was interrupted")
                    return response[1:]
                elif response[0] == Response.RX_TIMEOUT:
                    return None
                else:
                    raise PacketRadioError("RileyLink returned error code: %02X. Additional response data: %s"
                                         % (response[0], response[1:]), response[0])
        except Exception as e:
            raise PacketRadioError("Error executing command") from e
Exemplo n.º 2
0
def trigger_switchbot():
    p = Peripheral(MAC_ADDR, "random")
    hand_service = p.getServiceByUUID("cba20d00-224d-11e6-9fb8-0002a5d5c51b")
    hand = hand_service.getCharacteristics(
        "cba20002-224d-11e6-9fb8-0002a5d5c51b")[0]
    hand.write(binascii.a2b_hex("570100"))
    p.disconnect()
Exemplo n.º 3
0
    def turn_off(self, **kwargs):
        """Turn device off."""
        for connection in range(1, 6):
            try:
                p = Peripheral(self._mac, "random")
            except:
                _LOGGER.error('Connection attempt failed after %s tries' %
                              connection)
                time.sleep(10)
                continue

            break

        else:
            _LOGGER.error('Connection to Switchbot failed after max attempts')

        try:
            # p = Peripheral(self._mac, "random")
            hand_service = p.getServiceByUUID(
                "cba20d00-224d-11e6-9fb8-0002a5d5c51b")
            hand = hand_service.getCharacteristics(
                "cba20002-224d-11e6-9fb8-0002a5d5c51b")[0]
            hand.write(binascii.a2b_hex("570102"))
            p.disconnect()
            self._state = False
        except:
            _LOGGER.error("Cannot connect to switchbot.")
Exemplo n.º 4
0
class WavePlus():
    def __init__(self, MAC_ADDR):
        self.periph = None
        self.curr_val_char = None
        self.MacAddr = MAC_ADDR
        self.uuid = UUID("b42e4dcc-ade7-11e4-89d3-123b93f75cba")

    def connect(self):
        # Connect to device
        if (self.periph is None):
            self.periph = Peripheral(self.MacAddr)
        if (self.curr_val_char is None):
            self.curr_val_char = self.periph.getCharacteristics(
                uuid=self.uuid)[0]

    def read(self):
        if (self.curr_val_char is None):
            print("ERROR: Devices are not connected.")
            sys.exit(1)
        rawdata = self.curr_val_char.read()
        rawdata = struct.unpack('BBBBHHHHHHHH', rawdata)
        sensors = Sensors()
        sensors.set(rawdata)
        return sensors

    def disconnect(self):
        if self.periph is not None:
            self.periph.disconnect()
            self.periph = None
            self.curr_val_char = None
Exemplo n.º 5
0
class RobotController():
    def __init__(self, address):

        # Connect to the Romi over BLE
        self.robot = Peripheral(addr)
        print("connected")

        # Get service from robot
        self.sv = self.robot.getServiceByUUID(SERVICE_UUID)
        # Get characteristic handles from service/robot
        self.waypoint_cmd = self.sv.getCharacteristics(WAYPOINT_CMD_UUID)[0]
        self.ack = self.sv.getCharacteristics(ACK_UUID)[0]

        while True:
            # Check to see if the robot is ready to recieve a command
            ack, = struct.unpack("i", self.ack.read())
            if ack == 0:
                # The robot is ready to recieve a command
                # Get command as input from the user
                r = float(input("Distance (m): "))
                t = float(input("Angle (degrees): "))
                # Write to the appropriate characteristic
                # The waypoint command is a sequence of two floats, representing a polar coordiantes format
                self.waypoint_cmd.write(struct.pack('ff', *[r, t]))
                # Tell the robot that we want it to start executing our command
                self.ack.write(struct.pack('Bxxx', *[ack + 1]))
                # Give the robot some time to update the characteristic value before we read it again
                time.sleep(1)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.robot.disconnect()
Exemplo n.º 6
0
 def run(self):
     while True:
         if not switchqueue.empty():
             try:
                 item = switchqueue.get()
                 switch = item['on']
                 if switch:
                     val = '\x01'
                 else:
                     val = '\x00'
                 macaddress = self.convertMac(item['macaddress'])
                 device = Peripheral(macaddress, ADDR_TYPE_RANDOM,
                                     int(os.environ['SCAN_HCI']))
                 if item['newFirmware'] is False:
                     notifications = NotificationDelegate()
                     device.setDelegate(notifications)
                     auth_key = unhexlify(item['authkey'])
                     device.writeCharacteristic(STATE_NOTIFY_HANDLE,
                                                NOTIFY_VALUE, True)
                     device.writeCharacteristic(
                         STATE_HANDLE, sign('\x01' + val, auth_key))
                     while True:
                         if device.waitForNotifications(1.0):
                             device.disconnect()
                             print('Ending session')
                             break
                         print('Waiting for notification. Old Firmware.')
                 else:  # new firmware. No notifcation and no auth
                     device.writeCharacteristic(NEW_STATE_HANDLE, val, True)
                 device.disconnect()
             except Exception as e:
                 print(e)
         time.sleep(1)
Exemplo n.º 7
0
  def __get_raw_data(self,force_update = False):
    if self.__address is None:
      return

    starttime = int(time.time())

    if force_update or starttime - self.__cached_data['last_update'] > terrariumMiFloraSensor.__CACHE_TIMEOUT:
      try:
        miflora_dev = Peripheral(self.__address)
        #Read battery and firmware version attribute
        self.__cached_data['battery'], self.__cached_data['firmware'] = unpack('<xB5s',miflora_dev.readCharacteristic(terrariumMiFloraSensor.__MIFLORA_FIRMWARE_AND_BATTERY))

        #Enable real-time data reading
        miflora_dev.writeCharacteristic(terrariumMiFloraSensor.__MIFLORA_REALTIME_DATA_TRIGGER, str(bytearray([0xa0, 0x1f])), True)

        #Read plant data
        self.__cached_data['temperature'], self.__cached_data['light'], self.__cached_data['moisture'], self.__cached_data['fertility'] = unpack('<hxIBHxxxxxx',miflora_dev.readCharacteristic(terrariumMiFloraSensor.__MIFLORA_GET_DATA))
#        temperature, sunlight, moisture, fertility = unpack('<hxIBHxxxxxx',miflora_dev.readCharacteristic(53))

        # Close connection...
        miflora_dev.disconnect()

        self.__cached_data['last_update'] = starttime

      except Exception, ex:
        print ex
Exemplo n.º 8
0
def callback(msg):
    p = Peripheral("C4:D4:53:AB:ED:5B", "random")
    hand_service = p.getServiceByUUID("cba20d00-224d-11e6-9fb8-0002a5d5c51b")
    hand = hand_service.getCharacteristics(
        "cba20002-224d-11e6-9fb8-0002a5d5c51b")[0]
    hand.write(binascii.a2b_hex("570100"))
    p.disconnect()
Exemplo n.º 9
0
 def run(self):
     while True:
         if not switchqueue.empty():
             try:
                 item = switchqueue.get()
                 switch = item['on']
                 macaddress = self.convertMac(item['macaddress'])
                 auth_key = unhexlify(item['authkey'])
                 notifications = NotificationDelegate()
                 device = Peripheral(macaddress, ADDR_TYPE_RANDOM)
                 device.setDelegate(notifications)
                 device.writeCharacteristic(STATE_NOTIFY_HANDLE,
                                            NOTIFY_VALUE, True)
                 device.writeCharacteristic(
                     STATE_HANDLE,
                     sign('\x01' + ('\x00', '\x01')[switch], auth_key))
                 while True:
                     if device.waitForNotifications(1.0):
                         print('Ending session')
                         break
                     print('Waiting for notification')
                 device.disconnect()
             except Exception as e:
                 print(e)
         time.sleep(1)
Exemplo n.º 10
0
    def write_state(self, value):
        from bluepy.btle import Peripheral
        device = None
        try:
            # connect to device
            device = Peripheral(self._mac)
            # send PIN code auth
            device.writeCharacteristic(
                0x3c, self._pin.to_bytes(4, byteorder='little'), True)
            _LOGGER.info("Auth success for {}".format(self._mac))

            # set date+time
            now = datetime.now()
            device.writeCharacteristic(
                0x25,
                bytes([
                    now.minute, now.hour, now.day, now.month, now.year - 2000
                ]))

            # handle any outstanding value updates
            if value:
                device.writeCharacteristic(0x35, value, True)
                # writing something here does a "commit"
                device.writeCharacteristic(0x3a, bytes([randint(0, 255)]))
                _LOGGER.info("Updated switch to {}".format(value[0]))

            self._state = (device.readCharacteristic(0x35)[0] & 8 > 0)

        except Exception as e:
            _LOGGER.error("Exception: %s ", str(e))
        finally:
            if device is not None:
                device.disconnect()
Exemplo n.º 11
0
 def update(self, force_update=False):
     if force_update or (self._last_update is None) or (datetime.now() - self._min_update_inteval > self._last_update):
         self._lock.acquire()
         try:
             p = Peripheral(self._mac, "public")
             chList = p.getCharacteristics()
             for ch in chList:
                 if str(ch.uuid) == SERVICE_UUID:
                     if p.writeCharacteristic(ch.getHandle(), b'\x55\x03' + bytes([self.get_sequence()]) + b'\x11', True):
                         data = ch.read()
                         humihex = data[6:8]
                         temphex = data[4:6]
                         temp10 = int.from_bytes(temphex, byteorder='little')
                         humi10 = int.from_bytes(humihex, byteorder='little')
                         self._temperature = float(temp10) / 100.0
                         self._humidity = float(humi10) / 100.0
                         if p.writeCharacteristic(ch.getHandle(), b'\x55\x03' + bytes([self.get_sequence()]) + b'\x10', True):
                             data = ch.read()
                             battery10 = data[4]
                             self._battery = float(battery10) / 10.0
                     break
             p.disconnect()
         except Exception as ex:
             print("Unexpected error: {}".format(ex))
             p.disconnect()
         finally:
             self._lock.release()
Exemplo n.º 12
0
def get_service_value(addr: str, addr_type: str, offset: str):
    """
    Gets the value from a Blue Tooth Low Energy device.
    Arguments:
        addr {string} -- The address to get the value from
        add_type {string} -- The type of address we are using.
        offset {string} -- The offset from the device's address to get the value from
    Returns: {int} -- The result of the fetch
    """

    # Generate fake values for debugging
    # and for the development of the visuals.
    if not IS_LINUX:
        return 0

    try:
        p = Peripheral(addr, addr_type)
        ch_all = p.getCharacteristics(uuid=offset)

        if ch_all[0].supportsRead():
            res = ch_all[0].read()

        p.disconnect()

        return ord(res)
    except Exception as ex:
        print("   ex in get_name={}".format(ex))

    return None
Exemplo n.º 13
0
	def readData (self, mqttClient):
		print("reading data from device " + self.__mac)
		sys.stdout.flush()

		p = Peripheral(self.__mac, iface=HCI_INTERFACE)
		p.withDelegate(self.__delegate)

		try:
			battery = p.readCharacteristic(BATTERY_HANDLE)
			self.__lastBattery = battery[0]
		except:
			print("failed to read battery from " + self.__mac)
			sys.stdout.flush()

		p.writeCharacteristic(TEMP_HUM_WRITE_HANDLE, TEMP_HUM_WRITE_VALUE)
		if not p.waitForNotifications(3.0):
			print("failed to read data from " + self.__mac)
			sys.stdout.flush()

		try:
			p.disconnect()
		except:
			pass

		print("read data from " + self.__mac + " " + str(self.__lastTemp) + "," + str(self.__lastHum) + "," + str(self.__lastBattery))
		sys.stdout.flush()

		msg =\
		'{'\
			'"idx" : ' + str(self.__id) + ','\
			'"nvalue" : 0,'\
			'"svalue" : "' + str(self.__lastTemp) + ';' + str(self.__lastHum) + ';0",'\
			'"Battery" : ' + str(self.__lastBattery) + ' '\
		'}'
		mqttClient.publish(DEFAULT_IN_TOPIC, msg);
Exemplo n.º 14
0
class BluetoothManager:

    def __init__(self, mac=None):
        if mac is None:
            mac = '00:00:00:00:00'  # ~ Asumiendo la MAC del ESP32
        self.uuid = mac
        self.Open()

    def __async(self):
        while True:
            if self.per.waitForNotifications(1.0):
                # ~ Deberia ir al delegate
                continue
            print("Esperando...")

    def Open(self):
        self.per = Peripheral(self.uuid, ADDR_TYPE_RANDOM)
        # ~ Servicio definido en el ESP32
        self.srvc = self.per.getServiceByUUID('')
        # ~ Caracteristica definida
        self.esp_char = self.srvc.getCharacteristics('')[0]
        self.per.setDelegate(DelegateNotification(self.esp_char.getHandle()))

    def Send(self, trama):
        self.esp_char.write(trama)

    def Close(self):
        self.per.disconnect()
Exemplo n.º 15
0
def get_service_value(addr, addr_type, offset):
    """
    Gets the value from a Blue Tooth Low Energy device.
    Arguments:
        addr {string} -- The address to get the value from
        add_type {string} -- The type of address we are using.
        offset {string} -- The offset from the device's address to get the value from
    Returns: {int} -- The result of the fetch
    """

    # Generate fake values for debugging
    # and for the development of the visuals.
    if not IS_LINUX:
        if offset in CO_OFFSET:
            return int(aithre_co_simulator.get_value())
        else:
            return int(aithre_bat_simulator.get_value())

    try:
        p = Peripheral(addr, addr_type)  # bluepy.btle.ADDR_TYPE_PUBLIC)
        ch_all = p.getCharacteristics(uuid=offset)

        if ch_all[0].supportsRead():
            res = ch_all[0].read()

        p.disconnect()

        return ord(res)
    except Exception as ex:
        print("   ex in get_name={}".format(ex))

    return None
Exemplo n.º 16
0
def Dotwatch_Ble(name):
    print("BLE connecting....")
    p = Peripheral(DEVICE, "random")
    LedService = p.getServiceByUUID(led_service_uuid)

    print(LedService)
    ch = LedService.getCharacteristics(led_char_uuid)[0]
    print(ch)
    print("BLE connected")
    t = threading.currentThread()
    while getattr(t, "do_run", True):
        ch.write(struct.pack('BBB', 0x25, 0x01, 0x00))  # all up
        time.sleep(0.5)
        for char in name:
            #ch.write(struct.pack('BBBB', 0x0A,0x02,0x01,0x00))

            #print(type(char[0]))
            ch.write(
                struct.pack('BBBBBBBB', 0x06, 0x12, 0x01, 0x01, char[0],
                            char[1], char[2], char[3]))
            #print ("write : ",binascii.b2a_hex(ch.read()))
            if not getattr(t, "do_run", True):
                break
            time.sleep(8)
    #finally:
    #continue

    print("stop print dotwotch")
    ch.write(struct.pack('BBB', 0x26, 0x01, 0x00))  # all down
    p.disconnect()
    print("BLE disconnected")
Exemplo n.º 17
0
def putimage(addr, image):
    #  line below needs to be changed to use your mugs MAC address
    try:
        peripheral = Peripheral(addr, addrType=ADDR_TYPE_RANDOM)
        print("connected to muki")
        # line below uses characteristics directly. you can also request it
        characteristic = peripheral.getCharacteristics(
            uuid='06640002-9087-04a8-658f-ce44cb96b4a1')[0]
        print("writing image to device")

        characteristic.write(bytes.fromhex('74'), withResponse=True)
        # Write image in 291 chunks, 20 bytes at time
        index = 0
        for i in range(0, 291):
            data = image[index:index + 20]
            # last one may be too short
            while len(data) < 20:
                data.append(0xFF)
            characteristic.write(data, withResponse=False)
            index = index + 20

        # this one is write without response because it fails if response
        # is required. Image is written anyway
        characteristic.write(bytes.fromhex('64'), withResponse=True)
        peripheral.disconnect()
    except (BTLEException):
        print("Write failed")
        return False
    print("write successful")
    return True
Exemplo n.º 18
0
class BluepyBackend(AbstractBackend):
    def __init__(self, adapter='hci0'):
        super(self.__class__, self).__init__(adapter)
        self._peripheral = None

    def connect(self, mac):
        from bluepy.btle import Peripheral

        self._peripheral = Peripheral(mac)

    def disconnect(self):
        self._peripheral.disconnect()
        self._peripheral = None

    def read_handle(self, handle):
        if self._peripheral is None:
            raise BluetoothBackendException('not connected to backend')
        return self._peripheral.readCharacteristic(handle)

    def write_handle(self, handle, value):
        if self._peripheral is None:
            raise BluetoothBackendException('not connected to backend')
        return self._peripheral.writeCharacteristic(handle, value, True)

    def check_backend(self):
        try:
            import bluepy.btle  # noqa: F401
        except ImportError:
            raise BluetoothBackendException('bluepy not found')
Exemplo n.º 19
0
class Led:
    currentColor = '#FF00FF'
    currentBrightness = 100

    def __init__(self, address, uuid, characteristic):
        self.uuid = uuid
        self.address = address

        self.peripheral = Peripheral(address)
        self.service = self.peripheral.getServiceByUUID(uuid)
        self.device = self.service.getCharacteristics(characteristic)[0]

        self.set_brightness(self.currentBrightness)
        self.set_color(self.currentColor)

    # Set brightness intensity in percent
    def set_brightness(self, b):
        self.currentBrightness = b
        self.device.write(bytearray(brightness(b)))

    # Set color in hexadecimal format (ex: #FF00FF)
    def set_color(self, c):
        self.currentColor = c
        self.device.write(bytearray(color(c)))

    def stop(self):
        self.peripheral.disconnect()
Exemplo n.º 20
0
def push(address):
    p = Peripheral(address, 'random')
    hand_service = p.getServiceByUUID('cba20d00-224d-11e6-9fb8-0002a5d5c51b')
    hand = hand_service.getCharacteristics(
        'cba20002-224d-11e6-9fb8-0002a5d5c51b')[0]
    hand.write(binascii.a2b_hex('570100'))
    p.disconnect()
Exemplo n.º 21
0
 def disconnect(self):
     if (hasattr(self, 'enabled_notifs')):
         for n in self.enabled_notifs:
             print("Disabling %s service notifications status..." % n)
             getattr(self, 'cccd_' + n).write(b"\x00\x00", True)
             self.enabled_notifs.remove(n)
     Peripheral.disconnect(self)
Exemplo n.º 22
0
def read_from_ble_server(mac_address,
                         characteristic_uuid,
                         struct_unpack_type=None):
    '''
    Connecting to BLE server and reads characteristic by UUID

    Keyword arguments:
    mac_address -- MAC Address of BLE server
    characteristic_uuid -- UUID of characteristic to read value from
    struct_unpack_type -- char ( https://docs.python.org/3.7/library/struct.html#format-characters )

    Returns: string
    '''

    print(mac_address)
    print("+connecting...")
    characteristic_uuid = UUID(characteristic_uuid)
    val = None

    try:
        time.sleep(1)
        peripheral = Peripheral(mac_address, "public")
        time.sleep(1)
        val = read_characterictic(peripheral, characteristic_uuid,
                                  struct_unpack_type)
        time.sleep(1)
        peripheral.disconnect()

        print("+val: " + str(val))
    finally:
        return val
Exemplo n.º 23
0
def specific_scan(addr: str):
    try:
        dev = Peripheral(deviceAddr=addr)
        print_dev(dev)
        dev.disconnect()
    except BTLEException as e:
        print(f'Could not read device: {e}')
Exemplo n.º 24
0
class BluepyBackend(AbstractBackend):
    """Backend for Miflora using the bluepy library."""
    def __init__(self, adapter='hci0'):
        """Create new instance of the backend."""
        super(self.__class__, self).__init__(adapter)
        self._peripheral = None

    def connect(self, mac):
        """Connect to a device."""
        from bluepy.btle import Peripheral
        m = re.search(r'hci([\d]+)', self.adapter)
        if m is None:
            raise ValueError('Invalid pattern "{}" for BLuetooth adpater. '
                             'Expetected something like "hci0".'.format(
                                 self.adapter))
        iface = int(m.group(1))
        self._peripheral = Peripheral(mac, iface=iface)

    def disconnect(self):
        """Disconnect from a device."""
        self._peripheral.disconnect()
        self._peripheral = None

    def read_handle(self, handle):
        """Read a handle from the device.

        You must be connected to do this.
        """
        if self._peripheral is None:
            raise BluetoothBackendException('not connected to backend')
        return self._peripheral.readCharacteristic(handle)

    def write_handle(self, handle, value):
        """Write a handle from the device.

        You must be connected to do this.
        """
        if self._peripheral is None:
            raise BluetoothBackendException('not connected to backend')
        return self._peripheral.writeCharacteristic(handle, value, True)

    def check_backend(self):
        """Check if the backend is available."""
        try:
            import bluepy.btle  # noqa: F401
        except ImportError:
            raise BluetoothBackendException('bluepy not found')

    @staticmethod
    def scan_for_devices(timeout):
        """Scan for bluetooth low energy devices.

        Note this must be run as root!"""
        from bluepy.btle import Scanner

        scanner = Scanner()
        result = []
        for device in scanner.scan(timeout):
            result.append((device.addr, device.getValueText(9)))
        return result
Exemplo n.º 25
0
def startPWS(addr, ssid, psk):
    logger.info(f"Connect to device {addr}")

    grantorHandler = GrantorHandler(ssid, psk)

    # Init Peripheral, connect to it an set read delegate
    peripheral = Peripheral(addr, ADDR_TYPE_RANDOM)
    peripheral.setDelegate(WPNearbyReadDelegate(grantorHandler))

    pwsService = peripheral.getServiceByUUID(PWSGATTServiceUUID)
    pwsCharacteristic = pwsService.getCharacteristics(
        forUUID=PWSGATTCharacteristicUUID)[0]
    logger.debug(f"PWS characteristic: {pwsCharacteristic.getHandle()}")
    grantorHandler.pwsCharacteristic = pwsCharacteristic

    time.sleep(0.5)

    # Subscribe to the PWS characteristics by sending 0x0200 to pwsCharacteristic Handle+1 (Todo clean uo and check if it is always +1)
    peripheral.writeCharacteristic(pwsCharacteristic.getHandle() + 2,
                                   b"\x01\x00",
                                   withResponse=True)

    grantorHandler.sendPWS1()

    while peripheral.waitForNotifications(2):
        pass

    peripheral.disconnect()

    logger.info("Wi-Fi Password Sharing completed")
Exemplo n.º 26
0
class RobotController():
    def __init__(self, address):

        self.robot = Peripheral(addr)

        print("connected")

        # keep state for keypresses
        self.pressed = {"up": False, "down": False, "right": False, "left": False}
        # TODO get service from robot
        # TODO get characteristic handles from service/robot
        # TODO enable notifications if using notifications
        sv = self.robot.getServiceByUUID(SERVICE_UUID)
        self.ch_forward = sv.getCharacteristics(CHAR_UUIDS[0])[0]
        self.ch_backward = sv.getCharacteristics(CHAR_UUIDS[1])[0]
        self.ch_left = sv.getCharacteristics(CHAR_UUIDS[2])[0]
        self.ch_right = sv.getCharacteristics(CHAR_UUIDS[3])[0]

        keyboard.hook(self.on_key_event)

    def on_key_event(self, event):
        # print key name
        print(event.name)
        # if a key unrelated to direction keys is pressed, ignore
        if event.name not in self.pressed: return
        # if a key is pressed down
        if event.event_type == keyboard.KEY_DOWN:
            # if that key is already pressed down, ignore
            if self.pressed[event.name]: return
            # set state of key to pressed
            self.pressed[event.name] = True
            # TODO write to characteristic to change direction
            if event.name == "up":
                #print("writing forward")
                self.ch_forward.write(b'\x01')
            elif event.name == "down":
                #print("writing back")
                self.ch_backward.write(b'\x01')
            elif event.name == "right":
               # print("writing right")
                self.ch_right.write(b'\x01')
            elif event.name == "left":
                #print("writing left")
                self.ch_left.write(b'\x01')
        else:
            # set state of key to released
            self.pressed[event.name] = False
            # TODO write to characteristic to stop moving in this direction
            print("Stopping")
            self.ch_forward.write(b'\x00')
            self.ch_backward.write(b'\x00')
            self.ch_right.write(b'\x00')
            self.ch_left.write(b'\x00')


    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_value, traceback):
        self.robot.disconnect()
Exemplo n.º 27
0
class GAmonitor(object):

    SERVICE_UUIDS = [
        UUID('c0be9c58-a717-4e18-828c-a41836f0c7e5'),  # Sensors
    ]

    CHARACTERISTIC_UUIDS = {'9a067338-1da7-4e0f-8b4a-1e445e1e2df9': 'ACC'}

    NOTIFICATION_CHARACTERISTIC_UUIDS = [
        'ACC',
    ]

    # Notification data
    NOTIFICATION_ON = struct.pack("BB", 0x01, 0x00)
    NOTIFICATION_OFF = struct.pack("BB", 0x00, 0x00)

    def __init__(self, mac_address):
        self.macAddress = mac_address
        self.delegate = ScanDelegate()

    def set_delegate(self, delegate):
        self.delegate = delegate

    def connect(self):
        print('getting peripheral', sys.stderr)
        self.peripheral = Peripheral(self.macAddress, addrType='public')
        # Retrieve all characteristics from desired services and map them from their UUID
        self.peripheral.getServices()
        svc = self.peripheral.getServiceByUUID(
            "c0be9c58-a717-4e18-828c-a41836f0c7e5")
        characteristics = {
            svcid: svc.getCharacteristics()[i]
            for svcid, i in zip(self.CHARACTERISTIC_UUIDS, range(2))
        }

        print(characteristics, sys.stderr)

        # Store each characteristic's value handle for each characteristic name
        self.characteristicValueHandles = dict(
            (name, characteristics[uuid].getHandle())
            for uuid, name in self.CHARACTERISTIC_UUIDS.items())

        # Subscribe for notifications
        for name in self.NOTIFICATION_CHARACTERISTIC_UUIDS:
            print('Enabling notification: ', sys.stderr)
            self.peripheral.writeCharacteristic(
                self.characteristicValueHandles[name] + 1,
                self.NOTIFICATION_ON, True)
            print(name, sys.stderr)
            print(self.characteristicValueHandles[name] + 1, sys.stderr)

        self.peripheral.setDelegate(self.delegate)

    def disconnect(self):
        self.peripheral.disconnect()

    def wait_for_notifications(self, timeout):
        print('calling wait for notifications')
        return self.peripheral.waitForNotifications(timeout)
Exemplo n.º 28
0
def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))
    p = Peripheral(SWITCHBOT, "random")
    hand_service = p.getServiceByUUID("cba20d00-224d-11e6-9fb8-0002a5d5c51b")
    hand = hand_service.getCharacteristics(
        "cba20002-224d-11e6-9fb8-0002a5d5c51b")[0]
    hand.write(binascii.a2b_hex("570100"))
    p.disconnect()
Exemplo n.º 29
0
class MiTemperature(object):
    ''''
    Class to read the temperature from the MiTemp sensor from Amazon.
    Heavily based on https://github.com/JsBergbau/MiTemperature2 but refactored for my application
    '''
    def __init__(self, deviceAddr, addrType=ADDR_TYPE_PUBLIC, iface=0):
        self.deviceAddr = deviceAddr
        self.iface = iface
        self.addrType = addrType
        self.timeout = 10.0

    def _connect(self):
        self._periph = Peripheral(deviceAddr=self.deviceAddr,
                                  addrType=self.addrType,
                                  iface=self.iface)
        enable_notification_temp_humidity = b'\x01\x00'
        self._periph.writeCharacteristic(0x0038,
                                         enable_notification_temp_humidity,
                                         True)
        self._periph.writeCharacteristic(0x0046, b'\xf4\x01\x00', True)
        self._delegate = _MiDelegate()
        self._periph.withDelegate(self._delegate)
        logging.debug("Connected to {}".format(self.deviceAddr))
        self.measurement = self._delegate.measurement

    def _disconnect(self):
        self._periph.disconnect()

    def _reading(self):
        """
        Returns the most recent temperature reading
        :rtype: Measurement
        """

        self._connect()
        result = None
        if self._periph.waitForNotifications(self.timeout):
            logging.debug("Received notification")
            result = self._delegate.measurement
        else:
            logging.error("No trigger from delegate")
        self._disconnect()
        return result

    def reading(self):
        """"
        Return the readings a tuple of temperatiure, humidity, battery level
        :rtype: (float, float, float)
        """
        measurement = self._reading()
        return measurement.temperature, measurement.humidity, measurement.batterylevel

    def temperature(self):
        measurement = self._reading()
        if measurement is None:
            return None
        else:
            return measurement.temperature
def infect(dev):
    global connection_error
    infected = False
    # Connect.
    try:
        log(f"[*] Connecting to {dev.addr}.")
        peripheral = Peripheral(iface=BT_INTERFACE_INDEX)
        connection_error = False
        # Ugly hack to control the connection timout (only possible with threads).
        thread = Thread(target=connect, args=[peripheral, dev.addr])
        thread.start()
        thread.join(CONNECTION_TIMOUT)
        if thread.is_alive() or connection_error:
            raise Exception()
    except KeyboardInterrupt:
        raise
    except:
        try:
            peripheral.disconnect()
        except:
            pass
        log("[-] Could not connect.")
        return False

    # Check for service.
    try:
        service = peripheral.getServiceByUUID(
            "42230100-2342-2342-2342-234223422342")
        characteristic = service.getCharacteristics(
            "42230101-2342-2342-2342-234223422342")[0]
    except:
        log("[-] Service or characteristic not found. Not a card10 or connection lost."
            )
        return False

    # Write file.
    try:
        log("[*] Trying to write file.")
        data = OPEN_OR_CREATE_FILE + FILE_NAME
        characteristic.write(data)
        # Sleep is needed if the device was already paired (e.g. to a mobile phone) before.
        # Without the sleep the file will not be saved. I don't know why...
        sleep(0.1)
        # Writing files in this way caused weird errors. I haven't checked why.
        #data = WRITE_FILE + b"test"
        #characteristic.write(data)
        data = SAVE_FILE
        characteristic.write(data)
        log(f"[+] File written to {dev.addr}.", True)
        infected = True
    except:
        log("[-] Error on writing.")
        return False

    # Disconnect.
    peripheral.disconnect()
    return infected
Exemplo n.º 31
0
 def send_command(self, mac_address, service_uuid, characteristics,
                  command):
     p = Peripheral(mac_address)
     service_status = p.getServiceByUUID(service_uuid)
     ch = service_status.getCharacteristics(characteristics)[0]
     cmd = int(command)
     cmd = format(cmd, "b")
     ch.write(cmd, False)
     p.disconnect()
Exemplo n.º 32
0
    def write(self, characteristic, data):
        try:
            dev = Peripheral(self, self.addrType)

            services = sorted(dev.services, key=lambda s: s.hndStart)

            print_status("Searching for characteristic {}".format(characteristic))
            char = None
            for service in services:
                if char is not None:
                    break

                for _, c in enumerate(service.getCharacteristics()):
                    if str(c.uuid) == characteristic:
                        char = c
                        break

            if char:
                if "WRITE" in char.propertiesToString():
                    print_success("Sending {} bytes...".format(len(data)))

                    wwrflag = False

                    if "NO RESPONSE" in char.propertiesToString():
                        wwrflag = True

                    try:
                        char.write(data, wwrflag)
                        print_success("Data sent")
                    except Exception as err:
                        print_error("Error: {}".format(err))

                else:
                    print_error("Not writable")

            dev.disconnect()

        except Exception as err:
            print_error(err)

        try:
            dev.disconnect()
        except Exception:
            pass

        return None
Exemplo n.º 33
0
    def enumerate_services(self):
        print_status("Starting enumerating {} ({} dBm) ...".format(self.addr, self.rssi))

        try:
            dev = Peripheral(self, self.addrType)

            services = sorted(dev.services, key=lambda s: s.hndStart)

            data = []
            for service in services:
                if service.hndStart == service.hndEnd:
                    continue

                data.append([
                    "{:04x} -> {:04x}".format(service.hndStart, service.hndEnd),
                    self._get_svc_description(service),
                    "",
                    "",
                ])

                for _, char in enumerate(service.getCharacteristics()):
                    desc = self._get_char_description(char)
                    props = char.propertiesToString()
                    hnd = char.getHandle()
                    value = self._get_char(char, props)

                    data.append([
                        "{:04x}".format(hnd), desc, props, value
                    ])

            dev.disconnect()

            return data

        except Exception as err:
            print_error(err)

        try:
            dev.disconnect()
        except Exception as err:
            print_error(err)

        return None
Exemplo n.º 34
0
    
    print "Info, reading values!"
    ch = p.getCharacteristics(uuid=data_uuid)[0]
    
    rawVals = ch.read()
    rawVal = (ord(rawVals[1])<<8)+ord(rawVals[0])
    
    #object temp and ambient temp are calculated as shown below
    mantissa = rawVal & 0x0FFF;
    exponent = (rawVal >> 12) & 0xFF;

    magnitude = pow(2.0, exponent);
    output = (mantissa * magnitude);
    
    print "Lux: %4.2f lx" % (output / 100.0)

    print "Info, turning sensor off!"
    ch = p.getCharacteristics(uuid=config_uuid)[0]
    ch.write(sensorOff, withResponse=True)
    
  except:
    print "Fatal, unexpected error!"
    traceback.print_exc()
    raise

  finally:
    print "Info, disconnecting!"
    p.disconnect()
    
finally:
  quit()
Exemplo n.º 35
0
class OpenBCIGanglion(object):
    """
    Handle a connection to an OpenBCI board.

    Args:
      port: MAC address of the Ganglion Board. "None" to attempt auto-detect.
      aux: enable on not aux channels (i.e. switch to 18bit mode if set)
      impedance: measures impedance when start streaming
      timeout: in seconds, if set will try to disconnect / reconnect after a period without new data
       -- should be high if impedance check
      max_packets_to_skip: will try to disconnect / reconnect after too many packets are skipped
      baud, filter_data, daisy: Not used, for compatibility with v3
    """

    def __init__(self, port=None, baud=0, filter_data=False,
                 scaled_output=True, daisy=False, log=True, aux=False, impedance=False, timeout=2,
                 max_packets_to_skip=20):
        # unused, for compatibility with Cyton v3 API
        self.daisy = False
        # these one are used
        self.log = log  # print_incoming_text needs log
        self.aux = aux
        self.streaming = False
        self.timeout = timeout
        self.max_packets_to_skip = max_packets_to_skip
        self.scaling_output = scaled_output
        self.impedance = impedance

        # might be handy to know API
        self.board_type = "ganglion"

        print("Looking for Ganglion board")
        if port == None:
            port = self.find_port()
        self.port = port  # find_port might not return string

        self.connect()

        self.streaming = False
        # number of EEG channels and (optionally) accelerometer channel
        self.eeg_channels_per_sample = 4
        self.aux_channels_per_sample = 3
        self.imp_channels_per_sample = 5
        self.read_state = 0
        self.log_packet_count = 0
        self.packets_dropped = 0
        self.time_last_packet = 0

        # Disconnects from board when terminated
        atexit.register(self.disconnect)

    def getBoardType(self):
        """ Returns the version of the board """
        return self.board_type

    def setImpedance(self, flag):
        """ Enable/disable impedance measure """
        self.impedance = bool(flag)

    def connect(self):
        """ Connect to the board and configure it. Note: recreates various objects upon call. """
        print("Init BLE connection with MAC: " + self.port)
        print("NB: if it fails, try with root privileges.")
        self.gang = Peripheral(self.port, 'random')  # ADDR_TYPE_RANDOM

        print("Get mainservice...")
        self.service = self.gang.getServiceByUUID(BLE_SERVICE)
        print("Got:" + str(self.service))

        print("Get characteristics...")
        self.char_read = self.service.getCharacteristics(BLE_CHAR_RECEIVE)[0]
        print("receive, properties: " + str(self.char_read.propertiesToString()) +
              ", supports read: " + str(self.char_read.supportsRead()))

        self.char_write = self.service.getCharacteristics(BLE_CHAR_SEND)[0]
        print("write, properties: " + str(self.char_write.propertiesToString()) +
              ", supports read: " + str(self.char_write.supportsRead()))

        self.char_discon = self.service.getCharacteristics(BLE_CHAR_DISCONNECT)[0]
        print("disconnect, properties: " + str(self.char_discon.propertiesToString()) +
              ", supports read: " + str(self.char_discon.supportsRead()))

        # set delegate to handle incoming data
        self.delegate = GanglionDelegate(self.scaling_output)
        self.gang.setDelegate(self.delegate)

        # enable AUX channel
        if self.aux:
            print("Enabling AUX data...")
            try:
                self.ser_write(b'n')
            except Exception as e:
                print("Something went wrong while enabling aux channels: " + str(e))

        print("Turn on notifications")
        # nead up-to-date bluepy, cf https://github.com/IanHarvey/bluepy/issues/53
        self.desc_notify = self.char_read.getDescriptors(forUUID=0x2902)[0]
        try:
            self.desc_notify.write(b"\x01")
        except Exception as e:
            print("Something went wrong while trying to enable notification: " + str(e))

        print("Connection established")

    def init_streaming(self):
        """ Tell the board to record like crazy. """
        try:
            if self.impedance:
                print("Starting with impedance testing")
                self.ser_write(b'z')
            else:
                self.ser_write(b'b')
        except Exception as e:
            print("Something went wrong while asking the board to start streaming: " + str(e))
        self.streaming = True
        self.packets_dropped = 0
        self.time_last_packet = timeit.default_timer()

    def find_port(self):
        """Detects Ganglion board MAC address
        If more than 1 around, will select first. Needs root privilege.
        """

        print("Try to detect Ganglion MAC address. "
              "NB: Turn on bluetooth and run as root for this to work!"
              "Might not work with every BLE dongles.")
        scan_time = 5
        print("Scanning for 5 seconds nearby devices...")

        #   From bluepy example
        class ScanDelegate(DefaultDelegate):
            def __init__(self):
                DefaultDelegate.__init__(self)

            def handleDiscovery(self, dev, isNewDev, isNewData):
                if isNewDev:
                    print("Discovered device: " + dev.addr)
                elif isNewData:
                    print("Received new data from: " + dev.addr)

        scanner = Scanner().withDelegate(ScanDelegate())
        devices = scanner.scan(scan_time)

        nb_devices = len(devices)
        if nb_devices < 1:
            print("No BLE devices found. Check connectivity.")
            return ""
        else:
            print("Found " + str(nb_devices) + ", detecting Ganglion")
            list_mac = []
            list_id = []

            for dev in devices:
                # "Ganglion" should appear inside the "value" associated
                # to "Complete Local Name", e.g. "Ganglion-b2a6"
                for (adtype, desc, value) in dev.getScanData():
                    if desc == "Complete Local Name" and value.startswith("Ganglion"):
                        list_mac.append(dev.addr)
                        list_id.append(value)
                        print("Got Ganglion: " + value +
                              ", with MAC: " + dev.addr)
                        break
        nb_ganglions = len(list_mac)

        if nb_ganglions < 1:
            print("No Ganglion found ;(")
            raise OSError('Cannot find OpenBCI Ganglion MAC address')

        if nb_ganglions > 1:
            print("Found " + str(nb_ganglions) + ", selecting first")

        print("Selecting MAC address " + list_mac[0] + " for " + list_id[0])
        return list_mac[0]

    def ser_write(self, b):
        """Access serial port object for write"""
        self.char_write.write(b)

    def ser_read(self):
        """Access serial port object for read"""
        return self.char_read.read()

    def ser_inWaiting(self):
        """ Slightly different from Cyton API, return True if ASCII messages are incoming."""
        # FIXME: might have a slight problem with thread because of notifications...
        if self.delegate.receiving_ASCII:
            # in case the packet indicating the end of the message drops, we use a 1s timeout
            if timeit.default_timer() - self.delegate.time_last_ASCII > 2:
                self.delegate.receiving_ASCII = False
        return self.delegate.receiving_ASCII

    def getSampleRate(self):
        return SAMPLE_RATE

    def getNbEEGChannels(self):
        """Will not get new data on impedance check."""
        return self.eeg_channels_per_sample

    def getNbAUXChannels(self):
        """Might not be used depending on the mode."""
        return self.aux_channels_per_sample

    def getNbImpChannels(self):
        """Might not be used depending on the mode."""
        return self.imp_channels_per_sample

    def start_streaming(self, callback, lapse=-1):
        """
        Start handling streaming data from the board. Call a provided callback
        for every single sample that is processed

        Args:
          callback: A callback function or a list of functions that will receive a single argument
                    of the OpenBCISample object captured.
        """
        if not self.streaming:
            self.init_streaming()

        start_time = timeit.default_timer()

        # Enclose callback funtion in a list if it comes alone
        if not isinstance(callback, list):
            callback = [callback]

        while self.streaming:
            # should the board get disconnected and we could not wait for notification
            # anymore, a reco should be attempted through timeout mechanism
            try:
                # at most we will get one sample per packet
                self.waitForNotifications(1. / self.getSampleRate())
            except Exception as e:
                print("Something went wrong while waiting for a new sample: " + str(e))
            # retrieve current samples on the stack
            samples = self.delegate.getSamples()
            self.packets_dropped = self.delegate.getMaxPacketsDropped()
            if samples:
                self.time_last_packet = timeit.default_timer()
                for call in callback:
                    for sample in samples:
                        call(sample)

            if (lapse > 0 and timeit.default_timer() - start_time > lapse):
                self.stop()
            if self.log:
                self.log_packet_count = self.log_packet_count + 1

            # Checking connection -- timeout and packets dropped
            self.check_connection()

    def waitForNotifications(self, delay):
        """ Allow some time for the board to receive new data. """
        self.gang.waitForNotifications(delay)

    def test_signal(self, signal):
        """ Enable / disable test signal """
        if signal == 0:
            self.warn("Disabling synthetic square wave")
            try:
                self.char_write.write(b']')
            except Exception as e:
                print("Something went wrong while setting signal: " + str(e))
        elif signal == 1:
            self.warn("Eisabling synthetic square wave")
            try:
                self.char_write.write(b'[')
            except Exception as e:
                print("Something went wrong while setting signal: " + str(e))
        else:
            self.warn(
                "%s is not a known test signal. Valid signal is 0-1" % signal)

    def set_channel(self, channel, toggle_position):
        """ Enable / disable channels """
        try:
            # Commands to set toggle to on position
            if toggle_position == 1:
                if channel is 1:
                    self.ser.write(b'!')
                if channel is 2:
                    self.ser.write(b'@')
                if channel is 3:
                    self.ser.write(b'#')
                if channel is 4:
                    self.ser.write(b'$')
            # Commands to set toggle to off position
            elif toggle_position == 0:
                if channel is 1:
                    self.ser.write(b'1')
                if channel is 2:
                    self.ser.write(b'2')
                if channel is 3:
                    self.ser.write(b'3')
                if channel is 4:
                    self.ser.write(b'4')
        except Exception as e:
            print("Something went wrong while setting channels: " + str(e))

    """
  
    Clean Up (atexit)
  
    """

    def stop(self):
        print("Stopping streaming...")
        self.streaming = False
        # connection might be already down here
        try:
            if self.impedance:
                print("Stopping with impedance testing")
                self.ser_write(b'Z')
            else:
                self.ser_write(b's')
        except Exception as e:
            print("Something went wrong while asking the board to stop streaming: " + str(e))
        if self.log:
            logging.warning('sent <s>: stopped streaming')

    def disconnect(self):
        if (self.streaming == True):
            self.stop()
        print("Closing BLE..")
        try:
            self.char_discon.write(b' ')
        except Exception as e:
            print("Something went wrong while asking the board to disconnect: " + str(e))
        # should not try to read/write anything after that, will crash
        try:
            self.gang.disconnect()
        except Exception as e:
            print("Something went wrong while shutting down BLE link: " + str(e))
        logging.warning('BLE closed')

    """
  
        SETTINGS AND HELPERS
  
    """

    def warn(self, text):
        if self.log:
            # log how many packets where sent succesfully in between warnings
            if self.log_packet_count:
                logging.info('Data packets received:' +
                             str(self.log_packet_count))
                self.log_packet_count = 0
            logging.warning(text)
        print("Warning: %s" % text)

    def check_connection(self):
        """ Check connection quality in term of lag and number of packets drop.
         Reinit connection if necessary.
         FIXME: parameters given to the board will be lost.
         """
        # stop checking when we're no longer streaming
        if not self.streaming:
            return
        # check number of dropped packets and duration without new packets, deco/reco if too large
        if self.packets_dropped > self.max_packets_to_skip:
            self.warn("Too many packets dropped, attempt to reconnect")
            self.reconnect()
        elif self.timeout > 0 and timeit.default_timer() - self.time_last_packet > self.timeout:
            self.warn("Too long since got new data, attempt to reconnect")
            # if error, attempt to reconect
            self.reconnect()

    def reconnect(self):
        """ In case of poor connection, will shut down and relaunch everything.
        FIXME: parameters given to the board will be lost."""
        self.warn('Reconnecting')
        self.stop()
        self.disconnect()
        self.connect()
        self.init_streaming()
Exemplo n.º 36
0
def main():
    # uuid definition
    targetDevice = ""
    targetUUID   = UUID("08590f7e-db05-467e-8757-72f6f66666d4")
    # targetUUID   = UUID(0x2a2b)
    serviceUUID  = UUID("e20a39f4-73f5-4bc4-a12f-17d1ad666661")

    # scanning for Bluetooth LE device
    # P.S. root permission is needed
    print "scanning started..."
    scanner = Scanner().withDelegate(ScanDelegate())
    devices = scanner.scan(5)

    print "\n\nscanning completed...\n found %d device(s)\n" % len(devices)

    for dev in devices:
        print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
        for (adtype, desc, value) in dev.getScanData():
            print "  %s = %s" % (desc, value)

        try:
            p = Peripheral(dev.addr, "random")
            ch = p.getCharacteristics(uuid=targetUUID)
            if len(ch) > 0:
                print "the desired target found. the address is", dev.addr
                targetDevice = dev.addr
        except:
            # print "Unexpected error:", sys.exc_info()[0]
            print "Unable to connect"
            print " "
        finally:
            p.disconnect()

    # scanning completed, now continue to connect to device
    if targetDevice == "":
        # the target is not found. end.
        print "no target was found."
    else:
        # the target found, continue to subscribe.
        print "\n\nthe target device is ", targetDevice
        print "now try to subscribe..."

        try:
            # try to get the handle first
            p = Peripheral(targetDevice, "random")
            p.setDelegate(NotificationDelegate())
            # svc = p.getServiceByUUID(serviceUUID)
            ch = p.getCharacteristics(uuid=targetUUID)[0] # svc.getCharacteristics(targetUUID)[0]
            handle = ch.getHandle()
            print handle
            ch.write(struct.pack('<bb', 0x01, 0x00))
            # ch.write(bytes('aa', 'utf-8'))
            # p.writeCharacteristic(handle, struct.pack('<bb', 0x01, 0x00), True)

            print

            # Main loop
            while True:
                if p.waitForNotifications(5):
                    # handleNotification() was called
                    continue

                print "Waiting..."
                # Perhaps do something else here
        # except:
        #     print "Unexpected error:", sys.exc_info()[0]
        finally:
            p.disconnect()
class LightBlueBean(DefaultDelegate):
    # https://github.com/PunchThrough/bean-documentation/blob/master/app_message_types.md
    MSG_ID_SERIAL_DATA        = 0x0000
    MSG_ID_BT_SET_ADV         = 0x0500
    MSG_ID_BT_SET_CONN        = 0x0502
    MSG_ID_BT_SET_LOCAL_NAME  = 0x0504
    MSG_ID_BT_SET_PIN         = 0x0506
    MSG_ID_BT_SET_TX_PWR      = 0x0508
    MSG_ID_BT_GET_CONFIG      = 0x0510
    MSG_ID_BT_ADV_ONOFF       = 0x0512
    MSG_ID_BT_SET_SCRATCH     = 0x0514
    MSG_ID_BT_GET_SCRATCH     = 0x0515
    MSG_ID_BT_RESTART         = 0x0520
    MSG_ID_GATING             = 0x0550
    MSG_ID_BL_CMD             = 0x1000
    MSG_ID_BL_FW_BLOCK        = 0x1001
    MSG_ID_BL_STATUS          = 0x1002
    MSG_ID_CC_LED_WRITE       = 0x2000
    MSG_ID_CC_LED_WRITE_ALL   = 0x2001
    MSG_ID_CC_LED_READ_ALL    = 0x2002
    MSG_ID_CC_LED_DATA        = 0x2082
    MSG_ID_CC_ACCEL_READ      = 0x2010
    MSG_ID_CC_ACCEL_DATA      = 0x2090
    MSG_ID_CC_TEMP_READ       = 0x2011
    MSG_ID_CC_TEMP_DATA       = 0x2091
    MSG_ID_CC_BATT_READ       = 0x2015
    MSG_ID_CC_BATT_DATA       = 0x2095
    MSG_ID_AR_SET_POWER       = 0x3000
    MSG_ID_AR_GET_CONFIG      = 0x3006
    MSG_ID_DB_LOOPBACK        = 0xFE00
    MSG_ID_DB_COUNTER         = 0xFE01
    
    def __init__(self, mac):
        self.conn = Peripheral(mac)
        self.conn.setDelegate(self)
        self.count = 0
        self.buffin = [None]*10
        self.got1 = False
        print('connected')
        
        self.service = self.conn.getServiceByUUID(_LBN_UUID(0x10))
        self.serial = self.service.getCharacteristics(_LBN_UUID(0x11)) [0]
        
        #print(self.serial.propertiesToString())

        # Turn on notificiations
        self.conn.writeCharacteristic(0x2f, '\x01\x00', False)
        
        i = 0
        while True:
            #print(self.serial.read())
            self.write("a" * 60)
            #self.write("a" * 5)
            #self.sendCmd(LightBlueBean.MSG_ID_CC_ACCEL_READ)
            
            self.conn.waitForNotifications(1)
            time.sleep(1)
        self.conn.disconnect()
        
    def write(self, data):
        self.sendCmd(LightBlueBean.MSG_ID_SERIAL_DATA, data)

    def sendCmd(self, cmd, data = ""):
        # https://github.com/PunchThrough/bean-documentation/blob/master/serial_message_protocol.md
        gst = struct.pack("!BxH", len(data)+2, cmd) + data
        crc = struct.pack("<H", crc16(gst, 0xFFFF))
        gst += crc
        
        gt_qty = len(gst)/19
        if len(gst) % 19 != 0:
            gt_qty += 1
        
        #amnt = len(gst) / gt_qty
        optimal_packet_size = 19
        
        for ch in xrange(0, gt_qty):
            data = gst[:optimal_packet_size]
            gst = gst[optimal_packet_size:]
            
            gt = 0
            if ch == 0:
                gt = 0x80
            gt |= self.count << 5
            gt |= gt_qty - ch - 1
            
            gt = struct.pack("B", gt) + data
        
            #print("<", hexdump(gt))
            self.serial.write(gt)
            #time.sleep(0.1)
        
        self.count = (self.count + 1) % 4

    def writeRaw(self, data):
        self.conn.writeCharacteristic(0x0b, data, False)

    def handleNotification(self, cHandle, data):
        #print(">", hexdump(data))
        gt = struct.unpack("B", data[0]) [0]
        #gt_cntr = gt & 0x60
        gt_left = gt & 0x1F
        
        if gt & 0x80:
            self.got1 = True
            self.buffin = self.buffin[:gt_left+1]
            
        self.buffin[gt_left] = data[1:]
        
        if self.got1 and not self.buffin.count(None):
            #print("Got ", len(self.buffin), "packets")
            self.buffin.reverse()
            self.buffin = ''.join(self.buffin)
            
            crc_ = crc16(self.buffin[:-2], 0xFFFF)
            dlen, cmd = struct.unpack("!BxH", self.buffin[:4])
            crc = struct.unpack("<H", self.buffin[-2:]) [0]
            if crc == crc_:
                print(self.buffin[4:-2])
            else:
                print("CRC check failure")
            
            self.buffin = [None]*10
            self.got1 = False
class SBrickCommunications(threading.Thread, IdleObject):
    def __init__(self, sbrick_addr):
        threading.Thread.__init__(self)
        IdleObject.__init__(self)

        self.lock = threading.RLock()
        self.drivingLock = threading.RLock()
        self.eventSend = threading.Event()

        self.sBrickAddr = sbrick_addr
        self.owner_password = None

        self.brickChannels = [
            SBrickChannelDrive(0, self.eventSend),
            SBrickChannelDrive(1, self.eventSend),
            SBrickChannelDrive(2, self.eventSend),
            SBrickChannelDrive(3, self.eventSend),
        ]
        self.SBrickPeripheral = None
        self.stopFlag = False
        self.characteristicRemote = None
        self.need_authentication = False
        self.authenticated = False
        self.channel_config_ids = dict()

    def set_channel_config_id(self, channel, config_id):
        self.channel_config_ids[config_id] = channel
        self.brickChannels[channel].set_config_id(config_id)

    def terminate(self):
        self.stopFlag = True

    def is_driving(self):
        locked = self.drivingLock.acquire(False)
        if locked:
            self.drivingLock.release()
        return not locked

    def connect_to_sbrick(self, owner_password):
        self.owner_password = owner_password
        self.start()

    def run(self):
        try:
            monotime = 0.0

            self.SBrickPeripheral = Peripheral()
            self.SBrickPeripheral.connect(self.sBrickAddr)
            service = self.SBrickPeripheral.getServiceByUUID('4dc591b0-857c-41de-b5f1-15abda665b0c')
            characteristics = service.getCharacteristics('02b8cbcc-0e25-4bda-8790-a15f53e6010f')
            for characteristic in characteristics:
                if characteristic.uuid == '02b8cbcc-0e25-4bda-8790-a15f53e6010f':
                    self.characteristicRemote = characteristic

            if self.characteristicRemote is None:
                return

            self.emit('sbrick_connected')

            self.need_authentication = self.get_need_authentication()
            self.authenticated = not self.need_authentication
            if self.need_authentication:
                if self.password_owner is not None:
                    self.authenticate_owner(self.password_owner)

            while not self.stopFlag:
                if self.authenticated:
                    if monotonic.monotonic() - monotime >= 0.05:
                        self.send_command()
                        monotime = monotonic.monotonic()
                    self.eventSend.wait(0.01)
                    for channel in self.brickChannels:
                        if channel.decrement_run_timer():
                            monotime = 0.0
                            self.drivingLock.release()
                            # print("stop run normal")
                            self.emit("sbrick_channel_stop", channel.channel)
                        if channel.decrement_brake_timer():
                            self.drivingLock.release()
                            # print("stop brake timer")
                            monotime = 0.0
                            self.emit("sbrick_channel_stop", channel.channel)

            if self.authenticated:
                self.stop_all()
                self.send_command()
            self.SBrickPeripheral.disconnect()
            self.emit('sbrick_disconnected_ok')
        except BTLEException as ex:
            self.emit("sbrick_disconnected_error", ex.message)

    def get_channel(self, channel):
        if isinstance(channel, six.integer_types):
            return self.brickChannels[channel]
        if isinstance(channel, six.string_types):
            return self.brickChannels[self.channel_config_ids[channel]]
        return None

    def drive(self, channel, pwm, reverse, time, brake_after_time=False):
        with self.lock:
            ch = self.get_channel(channel)
            if ch is not None:
                ch.drive(pwm, reverse, time, brake_after_time)
                self.emit("sbrick_drive_sent", ch.channel, time)
            self.eventSend.set()

    def stop(self, channel, braked=False):
        with self.lock:
            ch = self.get_channel(channel)
            if ch is not None:
                ch.stop(braked)
                self.emit("sbrick_drive_sent", ch.channel, -2)
            self.eventSend.set()

    def stop_all(self):
        with self.lock:
            for channel in self.brickChannels:
                channel.stop()
            self.eventSend.set()

    def change_pwm(self, channel, pwm, change_reverse=False):
        with self.lock:
            ch = self.get_channel(channel)
            if ch is not None:
                ch.set_pwm(pwm, change_reverse)
            self.eventSend.set()

    def change_reverse(self, channel, reverse):
        with self.lock:
            ch = self.get_channel(channel)
            if ch is not None:
                ch.set_reverse(reverse)
            self.eventSend.set()

    def send_command(self):
        with self.lock:
            # try:
            drivecmd = bytearray([0x01])
            brakecmd = bytearray([0x00])
            for channel in self.brickChannels:
                drivecmd = channel.get_command_drive(drivecmd)
                brakecmd = channel.get_command_brake(brakecmd)
            if len(drivecmd) > 1:
                self.drivingLock.acquire()
                self.characteristicRemote.write(drivecmd, True)
                self.print_hex_string("drive sent", drivecmd)

            if len(brakecmd) > 1:
                self.characteristicRemote.write(brakecmd, True)
                self.print_hex_string("brake sent", brakecmd)
                # return True
                # except Exception as ex:
                #     self.emit("sbrick_disconnected_error",ex.message)
                #     return False

    def disconnect_sbrick(self):
        with self.lock:
            self.stopFlag = True

    @staticmethod
    def print_hex_string(what, strin):
        out = what + " -> "
        for chrx in strin:
            out = "%s %0X" % (out, chrx)
        print(out)

    def get_voltage(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b"\x0f\x00")
                value = self.characteristicRemote.read()
                valueint = struct.unpack("<H", value)[0]
                return (valueint * 0.83875) / 2047.0
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_temperature(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b"\x0f\x0e")
                value = self.characteristicRemote.read()
                valueint = struct.unpack("<H", value)[0]
                return valueint / 118.85795 - 160
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_thermal_limit(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x15')
                value = self.characteristicRemote.read()
                valueint = struct.unpack("<H", value)[0]
                return valueint / 118.85795 - 160
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_watchdog_timeout(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x0e')
                value = self.characteristicRemote.read()
                return struct.unpack("<B", value)[0] * 0.1
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_authentication_timeout(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x09')
                value = self.characteristicRemote.read()
                return struct.unpack("<B", value)[0] * 0.1
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_power_cycle_counter(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x28')
                value = self.characteristicRemote.read()
                return struct.unpack("<I", value)[0]
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_uptime(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x29')
                value = self.characteristicRemote.read()
                seconds = struct.unpack("<I", value)[0] * 0.1
                minutes = seconds // 60
                hours = minutes // 60
                return "%02d:%02d:%02d" % (hours, minutes % 60, seconds % 60)
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_hardware_version(self):
        try:
            return self.SBrickPeripheral.readCharacteristic(0x000c).decode("utf-8")
        except BTLEException as ex:
            self.emit("sbrick_disconnected_error", ex.message)

    def get_software_version(self):
        try:
            return self.SBrickPeripheral.readCharacteristic(0x000a).decode("utf-8")
        except BTLEException as ex:
            self.emit("sbrick_disconnected_error", ex.message)

    def get_brick_id(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x0a')
                value = self.characteristicRemote.read()
                return "%0X %0X %0X %0X %0X %0X" % (
                    value[0], value[1], value[2], value[3], value[4], value[5])
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_need_authentication(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x02')
                value = self.characteristicRemote.read()
                return struct.unpack("<B", value)[0] == 1
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_is_authenticated(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x03')
                value = self.characteristicRemote.read()
                return struct.unpack("<B", value)[0] == 1
            except BTLEException as ex:
                self.emit("sbrick_disconnected_error", ex.message)

    def get_user_id(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x04')
                value = self.characteristicRemote.read()
                return struct.unpack("<B", value)[0] == 1
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def authenticate_owner(self, password):
        with self.lock:
            try:
                self.authenticated = False
                cmd = bytearray([0x05, 0x00])
                for ch in password:
                    cmd.append(ord(ch))
                self.characteristicRemote.write(cmd)
                self.authenticated = True
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def authenticate_guest(self, password):
        with self.lock:
            try:
                self.authenticated = False
                cmd = bytearray([0x05, 0x01])
                for ch in password:
                    cmd.append(ord(ch))
                self.characteristicRemote.write(cmd)
                self.authenticated = True
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def clear_owner_password(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x06\x00')
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def clear_guest_password(self):
        with self.lock:
            try:
                self.characteristicRemote.write(b'\x06\x01')
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def set_owner_password(self, password):
        with self.lock:
            try:
                cmd = bytearray([0x07, 0x00])
                for ch in password:
                    cmd.append(ord(ch))
                self.characteristicRemote.write(cmd)
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def set_guest_password(self, password):
        with self.lock:
            try:
                cmd = bytearray([0x07, 0x01])
                for ch in password:
                    cmd.append(ord(ch))
                self.characteristicRemote.write(cmd)
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)

    def set_authentication_timeout(self, seconds):
        with self.lock:
            try:
                cmd = bytearray([0x08, seconds / 0.1])
                self.characteristicRemote.write(cmd)
            except BTLEException as ex:
                self.emit("sbrick_error", ex.message)