class PassiveDisconnect(object): def __init__(self, address): self.requester = GATTRequester(address, False) self.connect() self.wait_disconnection() def connect(self): print("Connecting...", end=' ') sys.stdout.flush() self.requester.connect(True) print("OK!") def wait_disconnection(self): status = "connected" if self.requester.is_connected( ) else "not connected" print("Checking current status: {}".format(status)) print( "\nNow, force a hardware disconnect. To do so, please switch off,\n" "reboot or move away your device. Don't worry, I'll wait...") while self.requester.is_connected(): time.sleep(1) print("\nOK. Current state is disconnected. Congratulations ;)")
class ActiveDisconnect(object): def __init__(self, address): self.requester = GATTRequester(address, False) self.connect() self.check_status() self.disconnect() self.check_status() def connect(self): print("Connecting...", end=' ') sys.stdout.flush() self.requester.connect(True) print("OK!") def check_status(self): status = "connected" if self.requester.is_connected() else "not connected" print("Checking current status: {}".format(status)) time.sleep(1) def disconnect(self): print("Disconnecting...", end=' ') sys.stdout.flush() self.requester.disconnect() print("OK!")
class SensorTag(object): def __init__(self, address): self.requester = GATTRequester(address, False) def connect(self): print("Connecting...") self.requester.connect(True) print("Succeed.") def check_status(self): status = "connected" if self.requester.is_connected() else "not connected" print("Checking current status: {}".format(status)) def disconnect(self): print("Disconnecting...") self.requester.disconnect() print("Succeed.") def show_primary(self): print("Discover Primary...") primary = self.requester.discover_primary() for prim in primary: print(prim) print("Done.") def show_characteristic(self): print("Discover Characteristic...") characteristic = self.requester.discover_characteristics() for char in characteristic: print(char) print("Done.")
class BleClient: def __init__(self, address): self.requester = GATTRequester(address, False) self.connect() self.request_data() def connect(self): print("~ BLE ~ Connecting...", end=' ') sys.stdout.flush() self.requester.connect(True) print("~ BLE ~ OK!") time.sleep(1) def disconnect(self): print("~ BLE ~ Disconnecting...", end=' ') sys.stdout.flush() self.requester.disconnect() print("~ BLE ~ OK!") time.sleep(1) def request_data(self, uuid="00002a00-0000-1000-8000-00805f9b34fb"): data = self.requester.read_by_uuid(uuid)[0] try: print("~ BLE ~ Device name:", data.decode("utf-8")) except AttributeError: print("~ BLE ~ Device name:", data) else: return data def wait_disconnection(self): status = "connected" if self.requester.is_connected( ) else "not connected" print("~ BLE ~ Checking current status: {}".format(status)) print( "\n~ BLE ~Now, force a hardware disconnect. To do so, please switch off,\n" "reboot or move away your device. Don't worry, I'll wait...") while self.requester.is_connected(): time.sleep(1) print("\n~ BLE ~OK. Current state is disconnected. Congratulations ;)")
def connect(deviceaddr): """ Attempt a connection to the target device - notoriously unreliable due to driver issues and the ephemeral nature of BTLE """ deviceHandle = GATTRequester(deviceaddr, False, args.listen_interface) flag = 0 device = None while flag<5: try: #bool wait,std::string channel_type, std::string security_level, int psm, int mtu) deviceHandle.connect(True, 'public','low') break except Exception,e: # We have a bunch of RuntimeErrors raised for various reasons by the GATTLib library -- lets handle those, then maybe fork GATTLib and get those to be more specific if type(e) == RuntimeError: if e.message == "Channel or attrib not ready": if deviceHandle.is_connected(): if args.debug == True: print "Device error" break # i don't think we can win #print 'w' #pdb.set_trace() #TODO: maybe see if it's connected or not? #flag += 1 # we don't want to get stuck here. #continue elif e.message == "Already connecting or connected": if deviceHandle.is_connected(): break else: time.sleep(3) if args.debug == True: print '\t Waiting for response to connection...' continue else: #errnum = int(e.message.split()[-1][1:-1]) #remove the ( and ) from the error number time.sleep(1) if args.debug == True: print '!!!' + e.message continue print e flag += 1
class MagicBlue: def __init__(self, mac_address): self.mac_address = mac_address self._connection = None def connect(self): """ Connect to device :return: True if connection succeed, False otherwise """ self._connection = GATTRequester(self.mac_address, False) try: self._connection.connect(True, "random") except RuntimeError as e: logger.error('Connection failed : {}'.format(e)) return False return True def disconnect(self): """ Disconnect from device """ self._connection.disconnect() def is_connected(self): """ :return: True if connection succeed, False otherwise """ return self._connection.is_connected() def set_color(self, rgb_color): """ Change bulb's color :param rgb_color: color as a list of 3 values between 0 and 255 """ self._connection.write_by_handle(HANDLE_CHANGE_COLOR, bytes(bytearray([MAGIC_CHANGE_COLOR] + list(rgb_color)))) def set_random_color(self): """ Change bulb's color with a random color """ self.set_color([random.randint(1, 255) for i in range(3)]) def turn_off(self): """ Turn off the light by setting color to black (rgb(0,0,0)) """ self.set_color([0, 0, 0]) def turn_on(self, brightness=1.0): """ Set white color on the light :param brightness: a float value between 0.0 and 1.0 defining the brightness """ self.set_color([int(255 * brightness) for i in range(3)])
def connect(self, device: str, interface: str = None, wait: bool = True, channel_type: str = 'public', security_level: str = 'low', psm: int = 0, mtu: int = 0, timeout: float = 10.0): """ Connect to a bluetooth LE device :param device: Device address to connect to :param interface: Bluetooth adapter name to use (default configured if None) :param wait: If True then wait for the connection to be established before returning (no timeout) :param channel_type: Channel type, usually 'public' or 'random' :param security_level: Security level - possible values: ['low', 'medium', 'high'] :param psm: PSM value (default: 0) :param mtu: MTU value (default: 0) :param timeout: Connection timeout if wait is not set (default: 10 seconds) """ from gattlib import GATTRequester req = self._req_by_addr.get(device) if req: if req.is_connected(): self.logger.info( 'Device {} is already connected'.format(device)) return self._req_by_addr[device] = None if not interface: interface = self.interface if interface: req = GATTRequester(device, False, interface) else: req = GATTRequester(device, False) self.logger.info('Connecting to {}'.format(device)) connect_start_time = time.time() req.connect(wait, channel_type, security_level, psm, mtu) if not wait: while not req.is_connected(): if time.time() - connect_start_time > timeout: raise TimeoutError( 'Connection to {} timed out'.format(device)) time.sleep(0.1) self.logger.info('Connected to {}'.format(device)) self._req_by_addr[device] = req
class MyConnecting(object): '''Connecting class''' def __init__(self, address): self.requester = GATTRequester(address, False) i = self.requester.is_connected() print(i) self.connect() def connect(self): print("connecting...", end='') sys.stdout.flush() self.requester.connect(True) print("Okay")
class PassiveDisconnect(object): def __init__(self, address): self.requester = GATTRequester(address, False) self.connect() self.wait_disconnection() def connect(self): print("Connecting...", end=' ') sys.stdout.flush() self.requester.connect(True) print("OK!") def wait_disconnection(self): status = "connected" if self.requester.is_connected() else "not connected" print("Checking current status: {}".format(status)) print("\nNow, force a hardware disconnect. To do so, please switch off,\n" "reboot or move away your device. Don't worry, I'll wait...") while self.requester.is_connected(): time.sleep(1) print("\nOK. Current state is disconnected. Congratulations ;)")
from gattlib import GATTRequester req = GATTRequester("C9:E8:56:3B:4D:B1", False) req.connect(True, "random") req.is_connected() print(req.discover_primary()) req.disconnect()
def post(host, data): r = requests.post("http://{}:{}/{}".format(host["ip"], host["port"], host["endpoint"]), data=data) print r.status_code, r.reason, r.text return r.text service = DiscoveryService() devices = service.discover(2) for addr, name in devices.items(): print("%s (%s)" % (name,addr)) print(name) if(name=="RapidPrototype"): req=GATTRequester(addr,False) req.connect(True) status="connected" if req.is_connected() else "not connectd" print(status) prevData="00" while(True): data=req.read_by_uuid("A495FF21-C5B1-4B44-B512-1370F02D74DE") data=str(data) data=data[4:6] if(data=="00" and prevData=="01"): print("Box is open") val = { "sensor_id": "pillbox", "value": 0 } post(host, val) if(data=="01" and prevData=="00"): print("Box is closed")
class MoveHub: address = "" controller = "" req = GATTRequester def __init__(self, address, controller): self.address = address self.controller = controller self.req = GATTRequester(self.address, False, self.controller) self.connect() def connect(self): if self.req.is_connected(): print("Already connected") else: print("Connecting...") sys.stdout.flush() self.req.connect(True) def is_connected(self): return self.req.is_connected() def getaddress(self): return self.address def getname(self): self.connect() devicename = self.req.read_by_handle(0x07) return devicename[0] def set_led_color(self, color): if color in LED_COLORS: self.connect() self.req.write_by_handle(HANDLE, SET_LED_COLOR[LED_COLORS.index(color)]) def motor_timed(self, motor, time_ms, dutycycle_pct): if motor in MOTORS: if dutycycle_pct in range(-100, 101): command = MOTOR_TIMED_INI command += motor command += MOTOR_TIMED_MID t = time_ms.to_bytes(2, byteorder='little') command += t if dutycycle_pct < 0: dutycycle_pct += 255 command += bytes(bytes(chr(dutycycle_pct), 'latin-1')) command += MOTOR_TIMED_END self.req.write_by_handle(HANDLE, command) def motors_timed(self, motor, time_ms, dutycycle_pct_A, dutycycle_pct_B): if motor in MOTOR_PAIRS: if dutycycle_pct_A in range(-100, 101) and dutycycle_pct_B in range(-100, 101): command = MOTORS_TIMED_INI command += motor command += MOTORS_TIMED_MID t = time_ms.to_bytes(2, byteorder='little') command += t if dutycycle_pct_A < 0: dutycycle_pct_A += 255 command += bytes(bytes(chr(dutycycle_pct_A), 'latin-1')) if dutycycle_pct_B < 0: dutycycle_pct_B += 255 command += bytes(bytes(chr(dutycycle_pct_B), 'latin-1')) command += MOTORS_TIMED_END self.req.write_by_handle(HANDLE, command)
class BLEConnectionManager(object): """BLEConnectionManager is used to manage a connection to a Bluetooth Low Energy device. This class allows us to connect, create a requester, create a response, and disconnect from a BLE device. :param address: MAC address (BD_ADDR) of target BTLE device :param adapter: BTLE adapter on host machine to use for connection (defaults to first found adapter). If an empty string is submitted, we connect to the host's default adapter. :param addressType: Type of address you want to connect to [public | random] :param securityLevel: Security level [low | medium | high] :param createRequester: When creating the connection manager, we can choose to create the requester or not. It can be helpful to set this to False when overriding methods in the GATTRequester class. :param psm: Specific PSM (default: 0) :param mtu: Specific MTU (default: 0) :type address: str :type adapter: str :type addressType: str :type securityLevel: str :type createRequester: bool :type psm: int :type mtu: int :ivar address: initial value: address :ivar adapter: initial value: adapter :ivar createRequester: initial value: createRequester :ivar requester: initial value: GATTRequester(address, False, adapter) if createRequester == True, else None :ivar responses: initial value: [] """ def __init__(self, address, adapter, addressType, securityLevel, createRequester=True, psm=0, mtu=0): self.address = address self.adapter = adapter self.requester = None self.responses = [] self.responseCounter = 0 self.addressType = addressType self.securityLevel = securityLevel self.psm = psm self.mtu = mtu if createRequester: self.createRequester() def __del__(self): if self.requester is not None and self.requester.is_connected(): self.disconnect() def createRequester(self): """Create a GATTRequester for the BLEConnectionManager :return: Returns the newly created requester :rtype: GATTRequester """ if self.adapter == "": self.requester = GATTRequester(self.address, False) else: self.requester = GATTRequester(self.address, False, self.adapter) return self.requester def setRequester(self, requester): """Sets the BLEConnectionManager's requester to the user-supplied GATTRequester :param requester: Custom GATTRequester :type requester: GATTRequester :return: None """ self.requester = requester def setResponse(self, response): """Sets the BLEConnectionManager's response to the user-supplied GATTResponse :param response: Custom GATTResponse :type response: GATTResponse :return: None """ self.response = response def createResponse(self, responseFunction=None): """Create a GATTResponse for the BLEConnectionManager. If a responseFunction is supplied, then the GATTResponse created will have an overridden on_response function. The responseFunction most only accept one parameter, which is the data contained in the response. The response is assigned an ID and stored in the response list. :param responseFunction: Function pointer called with a single parameter (data in response) when data is received. If not supplied, the GATTResponse function .received() can be called to access data (note: this function is not available if the responseFunction is specified) :type responseFunction: function pointer :return: Tuple with the response ID and response object :rtype: tuple (int, GATTResponse) """ class BLECustomResponse(GATTResponse): def __init__(self, responseFunction): super(BLECustomResponse, self).__init__() self.responseFunction = responseFunction def on_response(self, data): if self.responseFunction is not None: self.responseFunction(data) if responseFunction is not None: response = (self.responseCounter + 1, BLECustomResponse(responseFunction)) else: response = (self.responseCounter + 1, GATTResponse()) self.responses.append(response) self.responseCounter += 1 return response def isConnected(self): """ Return whether the connection manager's requester is still connected to a device :return: Return requester connection status :rtype: bool """ return self.requester.is_connected() def connect(self): """Connect to BLE device using BLEConnectionManager's requester :return: """ if not self.requester.is_connected(): self.requester.connect(True, self.addressType, self.securityLevel, self.psm, self.mtu) def disconnect(self): """Disconnect from BLE device using BLEConnectionManager's requester :return: """ self.requester.disconnect()
class SensorTag(object): def __init__(self, address): self.requester = GATTRequester(address, False) self.humidity = float(0.0) self.temperature = float(0.0) self.object_temperature = float(0.0) self.barometer = float(0.0) self.gyrometer = {"x": float(0.0), "y": float(0.0), "z": float(0.0)} self.acceleration = {"x": float(0.0), "y": float(0.0), "z": float(0.0)} self.geomagnetism = {"x": float(0.0), "y": float(0.0), "z": float(0.0)} self.lux = float(0.0) def connect(self): print("Connecting...") self.requester.connect(True) print("Succeed.") def check_status(self): status = "connected" if self.requester.is_connected( ) else "not connected" print("Checking current status: {}".format(status)) def disconnect(self): print(str("Disconnecting...")) self.requester.disconnect() print("Succeed.") def enable_humidity(self, enable): status = '\x01' if enable else '\x00' self.requester.write_by_handle(0x2f, status) def check_humidity(self): time.sleep(3) raw_data = self.requester.read_by_handle(0x2c)[0] raw_temp = (ord(raw_data[1]) << 8) + ord(raw_data[0]) raw_humi = (ord(raw_data[3]) << 8) + ord(raw_data[2]) self.temperature = round((float(raw_temp) / float(65536)) * 165 - 40, 1) self.humidity = round((float(raw_humi) / float(65536)) * 100, 1) def enable_IRtemperature(self, enable): status = '\x01' if enable else '\x00' self.requester.write_by_handle(0x27, status) def check_IRtemperature(self): time.sleep(3) raw_data = self.requester.read_by_handle(0x24)[0] raw_obj = (ord(raw_data[1]) << 8) + ord(raw_data[0]) raw_amb = (ord(raw_data[3]) << 8) + ord(raw_data[2]) self.object_temperature = round((float(raw_obj) / 4.0) * 0.03125, 1) self.temperature = round((float(raw_amb) / 4.0) * 0.03125, 1) def enable_Barometer(self, enable): status = '\x01' if enable else '\x00' self.requester.write_by_handle(0x37, status) def check_Barometer(self): time.sleep(3) raw_data = self.requester.read_by_handle(0x34)[0] raw_temp = (ord(raw_data[2]) << 16) + (ord(raw_data[1]) << 8) + ord( raw_data[0]) raw_baro = (ord(raw_data[5]) << 16) + (ord(raw_data[4]) << 8) + ord( raw_data[3]) self.temperature = round(float(raw_temp) / 100.0, 1) self.barometer = round(float(raw_baro) / 100.0, 1) def enable_9AxisSensor(self, enable): status = '\x7f\x00' if enable else '\x00\x00' self.requester.write_by_handle(0x3f, status) def check_9AxisSensor(self): time.sleep(3) raw_data = self.requester.read_by_handle(0x3c)[0] raw_gyro_x = struct.unpack('h', raw_data[0] + raw_data[1])[0] raw_gyro_y = struct.unpack('h', raw_data[2] + raw_data[3])[0] raw_gyro_z = struct.unpack('h', raw_data[4] + raw_data[5])[0] raw_acce_x = struct.unpack('h', raw_data[8] + raw_data[7])[0] raw_acce_y = struct.unpack('h', raw_data[10] + raw_data[9])[0] raw_acce_z = struct.unpack('h', raw_data[10] + raw_data[11])[0] raw_geom_x = struct.unpack('h', raw_data[12] + raw_data[13])[0] raw_geom_y = struct.unpack('h', raw_data[14] + raw_data[15])[0] raw_geom_z = struct.unpack('h', raw_data[16] + raw_data[17])[0] self.gyrometer["x"] = round(float(raw_gyro_x) / (65536 / 500), 2) self.gyrometer["y"] = round(float(raw_gyro_y) / (65536 / 500), 2) self.gyrometer["z"] = round(float(raw_gyro_z) / (65536 / 500), 2) #/2.0 ? /8.0 ? self.acceleration["x"] = float(raw_acce_x) / (32768.0 / 8.0) self.acceleration["y"] = float(raw_acce_y) / (32768.0 / 8.0) self.acceleration["z"] = float(raw_acce_z) / (32768.0 / 8.0) self.geomagnetism["x"] = float(raw_geom_x) self.geomagnetism["y"] = float(raw_geom_y) self.geomagnetism["z"] = float(raw_geom_z) def enable_Optical(self, enable): status = '\x01' if enable else '\x00' self.requester.write_by_handle(0x47, status) def check_Optical(self): raw_data = self.requester.read_by_handle(0x44)[0] raw_lux = (ord(raw_data[1]) << 8) + ord(raw_data[0]) raw_lux_m = raw_lux & 0b0000111111111111 raw_lux_e = (raw_lux & 0b1111000000000000) >> 12 self.lux = raw_lux_m * (0.01 * pow(2.0, raw_lux_e))