def scan(*, interface=0, delegate=None, timeout=10, passive=False): """Scan for Bluetooth devices. This function can only be called if the `bluepy` package is installed. Parameters ---------- interface : :class:`int`, optional The Bluetooth interface to use (where 0 is /dev/hci0). delegate : :ref:`DefaultDelegate <delegate>`, optional Receives a callback when broadcasts from devices are received. timeout : :class:`float`, optional Scan for devices for the given timeout in seconds. During this period, callbacks to the `delegate` object will be called. passive : :class:`bool`, optional Use active (to obtain more information when connecting) or passive scanning. Returns ------- A `view` of :ref:`ScanEntry <scanentry>` objects. """ from bluepy.btle import Scanner scanner = Scanner(interface) if delegate: scanner.withDelegate(delegate) return scanner.scan(timeout=timeout, passive=passive)
def run(self) -> None: scanner = Scanner() handler = BluetoothProximityHandler(self.flick_light_switch, self._threshold_rssi) scanner.withDelegate(handler) continue_loop = True while continue_loop: sleep(1) scanner.scan(60, passive=True)
def main(): print ("Running Server!") sys.stdout = MyLogger(logger, logging.INFO) sys.stderr = MyLogger(logger, logging.ERROR) sc = Scanner() scd = MiBand2ScanDelegate(sc) sc.withDelegate(scd) scan_thread = threading.Thread(target=scan_miband2, args=(sc,scd,)) scan_thread.start() for i in range(max_connections): t = threading.Thread(target=worker) t.daemon = True t.start() old_stats_registered = 0 old_stats_visible = 0 old_stats_outcd = 0 old_stats_incd = 0 while True: out_of_cd = [] for mb in scd.mibands.keys(): if mb in devices_last_sync.keys(): m = re.search("(\d+)-(\d+)-(\d+)\s+(\d+):(\d+)", devices_last_sync[mb]) if m.groups() != None: date = list(map(lambda x: int(x), m.groups())) ls = MiBand2Time(None, date[0], date[1], date[2], date[3], date[4]) if ls.minutesUntilNow() >= activity_fetch_cooldown: out_of_cd += [mb] else: out_of_cd += [mb] stats_registered = len(registered_devices) stats_visible = len(scd.visible_devices) stats_outcd = len(out_of_cd) stats_incd = len(scd.mibands.keys())-len(out_of_cd) if (stats_registered != old_stats_registered or stats_visible != old_stats_visible or stats_outcd != old_stats_outcd or stats_incd != old_stats_incd): print("Registered: {0} // Visible: {1} // Out of cooldown: {2} // In Cooldown: {3}".format( len(registered_devices), len(scd.visible_devices), len(out_of_cd), len(scd.mibands.keys())-len(out_of_cd))) for item in out_of_cd: q.put(item) q.join() if len(out_of_cd) > 0: save_sync(devices_last_sync) old_stats_registered = stats_registered old_stats_visible = stats_visible old_stats_outcd = stats_outcd old_stats_incd = stats_incd
def scan(timeout=5): scanner = Scanner() scanner.withDelegate(ScanAPI.ScanDelegate()) devices = scanner.scan(timeout) for dev in devices: print( "Device {} RSSI={} db, addrType={}, iface={}, connectable={}". format(dev.addr, dev.rssi, dev.addrType, dev.iface, dev.connectable))
def scan(timeout=5): scanner = Scanner() scanner.withDelegate(ScanAPI.ScanDelegate()) devices = scanner.scan(timeout) for dev in devices: print("Device {} ({}) ({}), RSSI={} db ".format( dev.addr, dev.addrType, dev.iface, dev.rssi)) for (adtype, desc, value) in dev.getScanData(): print(" {} = {}".format(desc, value))
def main(): scanthresh = -75 sc = Scanner() scd = MiBand2ScanDelegate(scanthresh) sc.withDelegate(scd) mibands = [] scan_thread = threading.Thread(target=scan_miband2, args=(sc,scanthresh)) scan_thread.start() while True: os.system('clear') mibands = copy.deepcopy(scd.tmp_devices) print "Mi Band 2 Scanner" print "Near Mi Bands 2: \t{0}".format(len(mibands)) print "------------------------------" for idx, mb in enumerate(mibands.values()): print "[{0}] {1}-{2} <{3}> ({4}dB) REP: {5}".format(idx, mb["device"].getValueText(9), mb["device"].getValueText(2), mb["device"].addr, mb["device"].rssi, mb["reputation"]) time.sleep(2) scan_thread.do_start = False
@app.route('/config/<endpoint>/', methods=["GET", "PUT"]) def server_config_detail(endpoint): if env.has_option('SERVER', endpoint): if request.method == "PUT": newval = request.form.get('config_value') env.set('SERVER', endpoint, str(newval)) return json.dumps({endpoint: env.get('SERVER', endpoint)}) else: abort(404) devices_keys = read_json(base_route + '/localdata/devices_keys.json') sc = Scanner() scd = MiBandScanDelegate(rssithreshold) sc.withDelegate(scd) scan_thread = threading.Thread(target=scan_miband2, args=( sc, rssithreshold, )) scan_thread.start() #ping_thread = threading.Thread(target=ping_connected, args=(pingtimer,)) #ping_thread.start() for i in range(max_connections): t = threading.Thread(target=worker) t.daemon = True t.start()
"addr": "dc:00:62:95:62:67", "type": "ambient" } } INFLUX_SERVER = os.environ.get("INFLUX_SERVER", None) or "raspberrypi.local" INFLUX_DATABASE = os.environ.get("INFLUX_DB", None) or "sensors" INFLUX_USER = os.environ.get("INFLUX_USER", None) or "root" INFLUX_PASSWORD = os.environ.get("INFLUX_PASSWORD", None) or "root" if __name__ == "__main__": print "Creating Scanner" delegate = DeviceForwardingDelegate() delegate.handlers.append(IGrillHandler(device_settings)) delegate.handlers.append(TokenCubeHandler(device_settings)) scanner = Scanner() scanner.withDelegate(delegate) print "Connecting to InfluxDB server" persistence = DataPersistence(INFLUX_SERVER, INFLUX_DATABASE, INFLUX_USER, INFLUX_PASSWORD) while True: print "Scanning..." scanner.scan(30) print "Persisting..." for handler in delegate.handlers: handler.persist_stats(persistence)
class MiBandCMD(cmd.Cmd): """Command Processor for intercating with many MiBands at a time""" def __init__(self): cmd.Cmd.__init__(self) threshold = -70 strikes = 5 pingtimer = 1 self.sc = Scanner() self.scd = MiBandScanDelegate(threshold) self.sc.withDelegate(self.scd) self.mibands = [] self.scan_thread = threading.Thread(target=scan_miband2, args=(self.sc,strikes,threshold)) self.scan_thread.start() #self.ping_thread = threading.Thread(target=ping_connected, args=(pingtimer,)) #self.ping_thread.start() for i in range(max_connections): t = threading.Thread(target=worker, args=(self,)) t.daemon = True t.start() self.prompt = 'MBS => ' def exit_safely(self): self.scan_thread.do_scan = False #self.ping_thread.do_ping = False self.scan_thread.join() print ("Disconnecting from %s devices" % len(connected_devices.values())) for con in connected_devices.values(): con.disconnect() return True def do_devices(self, line): tmp_mibands = copy.deepcopy(self.scd.tmp_devices) self.mibands = {k: v["device"] for k, v in tmp_mibands.items()} self.models = {k: v["model"] for k, v in tmp_mibands.items()} tmp_strikes = {k: v["strikes"] for k, v in tmp_mibands.items()} for idx,mb in enumerate(self.mibands.keys()): name = "Someone" uid = 0 udata = None if args.mode == "db": devid = mbdb.get_device_id(cnxn_string, mb.upper()) devuser = mbdb.get_device_user(cnxn_string, devid) if devuser != -1: udata = mbdb.get_user_data(cnxn_string,devuser) else: udata = None else: # TODO: User Data on local storage??? pass if udata: name = udata["alias"] uid = udata["id"] model = self.models[self.mibands.keys()[idx]].upper() str = "[%s]%10s's %s <U:%05d> (%s) %sdB S:%s " % (idx, name, model, uid, mb, self.mibands[self.mibands.keys()[idx]].rssi, "X"*tmp_strikes[self.mibands.keys()[idx]]) if (args.mode == "db" and mbdb.is_device_registered(cnxn_string, mb)) or (args.mode == "json" and mb in self.registered_devices): str += "[R]" if mb in connected_devices: mb_dev = connected_devices[mb] if args.mode == "db": mbdb.update_battery(cnxn_string, mb_dev.addr, mb_dev.battery_info['level']) str += "[C] [B:{0:03d}%]".format(mb.battery_info["level"]) print str def do_reboot(self, params): try: dev_id = int(params) except ValueError: print "*** arguments should be numbers" return except IndexError: print "*** alert takes at least one parameter" return if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or (args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices)): if self.mibands.keys()[dev_id] in connected_devices.keys(): try: mb = connected_devices[self.mibands.keys()[dev_id]] mb.reboot() except BTLEException: print("There was a problem rebooting this MiBand, try again later") else: print("That MiBand is not connected!") else: print("That MiBand is not registered") def do_alert(self, params): l = params.split() if len(l)!=2: print "*** invalid number of arguments" return try: l = [int(i) for i in l] except ValueError: print "*** arguments should be numbers" return except IndexError: print "*** alert takes at least one parameter" return dev_id = int(l[0]) if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return alert_int = int(l[1]) if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if self.mibands.keys()[dev_id] in connected_devices.keys(): try: mb = connected_devices[self.mibands.keys()[dev_id]] data = struct.pack('B', alert_int) mb.send_alert(data) print "Sending Notification: " + binascii.hexlify(data) except BTLEException: print("There was a problem alerting this MiBand, try again later") else: print("That MiBand is not connected!") else: print("That MiBand is not registered") def do_configure(self, params): l = params.split() try: dev_id = int(l[0]) command = "" if len(l) > 1: command = l[1] except ValueError: print "*** argument 1 should be number" return except IndexError: print "*** configure takes at least one parameter" return if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if command == "": print("Using default configuration preset [%s]" % CONFIG_MODE) command = CONFIG_MODE if not config.has_section(command): print "*** invalid configuration preset '%s'" % command return self.configure_miband(dev_id, command) def configure_miband(self, dev_id, preset): if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if self.mibands.keys()[dev_id] in connected_devices.keys(): try: mb = connected_devices[self.mibands.keys()[dev_id]] print("Configuring MiBand to [%s] presets" % preset) if config.has_option(preset, "MonitorHRSleep"): mb.monitorHeartRateSleep(config.getint(preset, "MonitorHRSleep")) if config.has_option(preset, "MonitorHRInterval"): mb.setMonitorHeartRateInterval(config.getint(preset, "MonitorHRInterval")) if config.has_option(preset, "DisplayTimeFormat"): mb.setDisplayTimeFormat(config.get(preset, "DisplayTimeFormat")) if config.has_option(preset, "DisplayTimeHours"): mb.setDisplayTimeHours(config.getint(preset, "DisplayTimeHours")) if config.has_option(preset, "DistanceUnit"): mb.setDistanceUnit(config.get(preset, "DistanceUnit")) if config.has_option(preset, "LiftWristActivate"): mb.setLiftWristToActivate(config.getint(preset, "LiftWristActivate")) if config.has_option(preset, "RotateWristSwitch"): mb.setRotateWristToSwitchInfo(config.getint(preset, "RotateWristSwitch")) if config.has_option(preset, "DisplayItems"): disp = [x.strip() for x in config.get(preset, 'DisplayItems').split(',')] steps = True if 'steps' in disp else False distance = True if 'distance' in disp else False calories = True if 'calories' in disp else False heartrate = True if 'heartrate' in disp else False battery = True if 'battery' in disp else False mb.setDisplayItems(steps=steps, distance=distance, calories=calories, heartrate=heartrate, battery=battery) if config.has_option(preset, "DoNotDisturb"): enableLift = config.getint(preset, "DoNotDisturbLift") if config.has_option(preset, "DoNotDisturbLift") else 1 mb.setDoNotDisturb(config.get(preset, "DoNotDisturb"), enableLift=enableLift) if config.has_option(preset, "InactivityWarnings"): start = config.getint(preset, "InactivityWarningsStart") if config.has_option(preset, "InactivityWarningsStart") else 8 end = config.getint(preset, "InactivityWarningsEnd") if config.has_option(preset, "InactivityWarningsEnd") else 19 threshold = config.getint(preset, "InactivityWarningsThresholdHours") if config.has_option(preset, "InactivityWarningsThresholdHours") else 1 mb.setInactivityWarnings(config.getint(preset, "InactivityWarnings"), threshold=threshold*60, start=(start, 0), end=(end, 0)) if config.has_option(preset, "DisplayCaller"): mb.setDisplayCaller(config.getint(preset, "DisplayCaller")) except BTLEException as e: print("There was a problem configuring this MiBand, try again later") print e else: print("That MiBand is not connected, please connect it before configuring.") else: print("That MiBand is not registered, please register it before configuring.") def do_setuser(self, params): try: l = params.split() dev_id = int(l[0]) if args.mode == "db": user_id = int(l[1]) else: # TODO: Not persisted user_alias = l[1] if l[2] == "M": user_gender = 0 elif l[2] == "F": user_gender = 1 else: user_gender = 2 user_bd_year = int(l[3]) user_bd_month = int(l[4]) user_bd_day = 0 user_weight = float(l[5]) user_height = int(l[6]) position = None if l[2] == "left": position = (0, "left") elif l[2] == "right": position = (1, "right") else: print("*** only left and right supported") return except ValueError: print "*** argument should be number" return except IndexError: print "*** setuser takes at least one parameter" return if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if args.mode == "db": udata = mbdb.get_user_data(cnxn_string, user_id) if udata or args.mode == "json": if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if self.mibands.keys()[dev_id] in connected_devices.keys(): mb = connected_devices[self.mibands.keys()[dev_id]] if args.mode == "db": if mbdb.set_device_user(cnxn_string, mb.addr, user_id, position[0]): mb.setUserInfo(udata["alias"], udata["sex"], udata["height"], udata["weight"], udata["birth"]) else: mb.setUserInfo(user_alias, user_gender, user_height, user_weight, (user_bd_year, user_bd_month, user_bd_day)) mb.setWearLocation(position[1]) else: print("MiBand should be connected before setting user data") else: print("MiBand should be registered before setting user data") else: print("*** user with id %s doesn't exist" % user_id) def do_reluser(self, params): if args.mode == "db": try: l = params.split() dev_id = int(l[0]) user_id = int(l[1]) except ValueError: print "*** argument should be number" return except IndexError: print "*** reluser takes at least one parameter" return if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return udata = mbdb.get_user_data(cnxn_string, user_id) if udata: if mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id]): if self.mibands.keys()[dev_id] in connected_devices.keys(): mb = connected_devices[self.mibands.keys()[dev_id]] if mbdb.release_device_user(cnxn_string, mb.addr, user_id): print "MiBand Released from user" else: print "There was a problem releasing this MiBand" else: print("MiBand should be connected before releasing user data") else: print("MiBand should be registered before releasing user data") else: print("*** user with id %s doesn't exist" % user_id) else: # TODO: If storage, release properly print("This operation is only available for DB mode") def do_connect(self, params): try: l = int(params) except ValueError: print "*** argument should be number" return except IndexError: print "*** connect takes at least one parameter" return dev_id = l if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if len(connected_devices.keys()) >= 5: print("Can't connect to more than 5 devices at the same time, disconnect some") else: if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if self.mibands.keys()[dev_id] in connected_devices.keys(): print("That MiBand is already connected") else: try: addr = self.mibands.keys()[dev_id] model = self.models[addr] if not addr in self.devices_keys.keys(): self.devices_keys[addr] = random_key() if model.upper() == "MB2": mb = MiBand2(addr, self.devices_keys[addr], initialize=False) elif model.upper() == "MB3": mb = MiBand3(addr, self.devices_keys[addr], initialize=False) connected_devices[self.mibands.keys()[dev_id]] = mb if args.mode == "db": alarms = mbdb.get_device_alarms(cnxn_string, mb.addr) mbdb.update_battery(cnxn_string, mb.addr, mb.battery_info['level']) else: if mb.addr in self.devices_alarms.keys(): alarms = self.devices_alarms[mb.addr] else: alarms = [] for a in alarms: mb.alarms += [MiBandAlarm(a["hour"], a["minute"], enabled=a["enabled"], repetitionMask=a["repetition"])] except BTLEException as e: print("There was a problem connecting to this MiBand, try again later") print e else: print("You have to register the MiBand before connecting to it") def do_disconnect(self, params): try: l = int(params) except ValueError: print "*** argument should be number" return except IndexError: print "*** disconnect takes at least one parameter" return dev_id = l if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if self.mibands.keys()[dev_id] in connected_devices.keys(): try: mb = connected_devices[self.mibands.keys()[dev_id]] mb.disconnect() del connected_devices[self.mibands.keys()[dev_id]] del mb print ("MiBand disconnected!") except BTLEException as e: print("There was a problem disconnecting this MiBand, try again later") print e else: print("That MiBand isn't connected!") def do_register(self, params): try: l = int(params) except ValueError: print "*** argument should be number" return except IndexError: print "*** register takes at least one parameter" return dev_id = l if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): print("That MiBand is already registered") else: mb = None try: addr = self.mibands.keys()[dev_id] model = self.models[addr] if not addr in self.devices_keys.keys(): self.devices_keys[addr] = random_key() if model.upper() == "MB2": mb = MiBand2(addr, self.devices_keys[addr], initialize=False) elif model.upper() == "MB3": mb = MiBand3(addr, self.devices_keys[addr], initialize=False) mb.cleanAlarms() if args.mode == "db": dev_id = mbdb.get_device_id(cnxn_string, mb.addr) mbdb.delete_all_alarms(cnxn_string, dev_id) mbdb.register_device(cnxn_string, mb.addr) mbdb.update_battery(cnxn_string, mb.addr, mb.battery_info['level']) else: self.registered_devices += [mb.addr] # Device stays connected after initialize, but we don't want that mb.disconnect() except BTLEException as e: print("There was a problem registering this MiBand, try again later") print e except KeyError as e: print("Device was kicked out") print e def do_unregister(self, params): try: l = int(params) except ValueError: print "*** argument should be number" return except IndexError: print "*** unregister takes at least one parameter" return dev_id = l if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if not self.mibands.keys()[dev_id] in connected_devices.values(): try: if args.mode == "db": mbdb.unregister_device(cnxn_string, self.mibands.keys()[dev_id]) mbdb.delete_all_alarms(cnxn_string, self.mibands.keys()[dev_id]) else: self.registered_devices.remove(self.mibands.keys()[dev_id]) del self.devices_keys[self.mibands.keys()[dev_id]] print("MiBand unregistered!") except BTLEException: print("There was a problem unregistering this MiBand, try again later") else: print("Disconnect the miBand2 first!") else: print("That MiBand is not registered") def do_activity(self, params): try: l = int(params) except ValueError: print "*** argument should be number" return except IndexError: print "*** activity takes at least one parameter" return dev_id = l if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if self.mibands.keys()[dev_id] in connected_devices.keys(): q.put(self.mibands.keys()[dev_id]) q.join() else: print("MiBand should be connected before fetching activity data") else: print("MiBand should be registered before fetching activity data") def do_alarms(self, params): l = params.split() try: dev_id = int(l[0]) command = "list" if len(l) > 1: command = l[1] except ValueError: print "*** argument 1 should be number" return except IndexError: print "*** alarms takes at least one parameter" return if command not in ['list', 'queue', 'set', 'toggle', 'toggleday', 'delete', 'clear']: print "*** invalid alarm command, see help" return if dev_id >= len(self.mibands.keys()): print "*** device not in the device list" return if ((args.mode == "db" and mbdb.is_device_registered(cnxn_string, self.mibands.keys()[dev_id])) or args.mode == "json" and self.mibands.keys()[dev_id] in self.registered_devices): if self.mibands.keys()[dev_id] in connected_devices.keys(): mb = connected_devices[self.mibands.keys()[dev_id]] if args.mode == "db": alarms = mbdb.get_device_alarms(cnxn_string, self.mibands.keys()[dev_id]) else: if self.mibands.keys()[dev_id] in self.devices_alarms.keys(): alarms = self.devices_alarms[self.mibands.keys()[dev_id]] else: alarms = [] if command == 'list': if len(alarms) > 0: for idx,a in enumerate(mb.alarms): print "[%s]" % idx + str(a) if command == 'clear': if len(alarms) > 0: mb.cleanAlarms() if args.mode == "db": mbdb.delete_all_alarms(cnxn_string, mb.addr) else: self.devices_alarms[self.mibands.keys()[dev_id]] = [] elif command == 'queue': try: hour, minute = map(lambda x: int(x), l[2].split(":")) alarm_id = mb.queueAlarm(hour, minute) if args.mode == "db": mbdb.set_alarm(cnxn_string, mb.addr, mb.alarms[alarm_id], alarm_id) else: if len(alarms) > 0: self.devices_alarms[self.mibands.keys()[dev_id]] += [{"enabled": True, "repetition": 128, "hour": hour, "minute": minute}] else: self.devices_alarms[self.mibands.keys()[dev_id]] = [{"enabled": True, "repetition": 128, "hour": hour, "minute": minute}] except IndexError: print "*** queue takes an hour parameter in format HH:MM" except ValueError: print "*** queue takes an hour parameter in format HH:MM" elif command == 'delete': try: alarm_id = int(l[2]) mb.deleteAlarm(alarm_id) if len(alarms) > 0: if args.mode == "db": mbdb.delete_alarm(cnxn_string, mb.addr, alarm_id) else: del self.devices_alarms[self.mibands.keys()[dev_id]][alarm_id] except IndexError: print "*** delete takes an alarm_id parameter" except ValueError: print "*** delete's alarm_id should be a number" elif command == 'toggle': try: alarm_id = int(l[2]) mb.toggleAlarm(alarm_id) if args.mode == "db": mbdb.set_alarm(cnxn_string, mb.addr, mb.alarms[alarm_id], alarm_id) else: self.devices_alarms[self.mibands.keys()[dev_id]][alarm_id]["enabled"] = mb.alarms[alarm_id].enabled except IndexError: print "*** toggle takes an alarm_id parameter" except ValueError: print "*** toggle's alarm_id should be a number" elif command == 'toggleday': try: alarm_id = int(l[2]) day_id = int(l[3]) if day_id not in range(1,8): print "*** day_id should be between 1 (Monday) and 7 (Sunday)" return else: mb.toggleAlarmDay(alarm_id, day_id-1) if args.mode == "db": mbdb.set_alarm(cnxn_string, mb.addr, mb.alarms[alarm_id], alarm_id) else: self.devices_alarms[self.mibands.keys()[dev_id]][alarm_id]["repetition"] = mb.alarms[alarm_id].repetitionMask except IndexError: print "*** toggleday takes an alarm_id parameter and a day_id parameter (1-7)" except ValueError: print "*** toggleday's alarm_id and day_id should be both numbers" elif command == "set": try: alarm_id = int(l[2]) hour, minute = map(lambda x: int(x), l[3].split(":")) mb.changeAlarmTime(alarm_id, hour, minute) if args.mode == "db": mbdb.set_alarm(cnxn_string, mb.addr, mb.alarms[alarm_id], alarm_id) else: self.devices_alarms[self.mibands.keys()[dev_id]][alarm_id]["hour"] = mb.alarms[alarm_id].hour self.devices_alarms[self.mibands.keys()[dev_id]][alarm_id]["minute"] = mb.alarms[alarm_id].minute except IndexError: print "*** set takes an alarm_id parameter and an hour parameter in format HH:MM" except ValueError: print "*** toggleday's alarm_id and hour (HH:MM) should be both numbers" else: print("MiBand should be connected before viewing/changing alarms") else: print("MiBand should be registered before viewing/changing alarms") def do_save(self, line): if args.mode == "json": print("Saving local data") save_local(self) else: print("This command is only available to local mode") def do_exit(self, line): print("Saving local data before exiting") save_local(self) return self.exit_safely() def do_EOF(self, line): print("Saving local data before exiting") save_local(self) return self.exit_safely()
def connect(self): if self.target_address is None: sys.stdout.write("Searching for devices....") sys.stdout.flush() scanner = Scanner(self.port) scanner.withDelegate(ScanDelegate()) nearby_devices = scanner.scan(10) if len(nearby_devices) > 0: for dev in nearby_devices: #look for a device name that starts with the specified target name for (adtype, desc, value) in dev.getScanData(): #one of the data points returned by getScanData is the device's #human-readable name. This is what we want to match against to see #if we have discovered a Sphero device. if value.startswith(self.target_name): self.found_device = True self.target_address = dev.addr break if self.found_device: break if self.target_address is not None: sys.stdout.write("\nFound Sphero device with address: %s\n" % (self.target_address)) sys.stdout.flush() else: sys.stdout.write("\nNo Sphero devices found.\n") sys.stdout.flush() sys.exit(1) else: sys.stdout.write("Connecting to device: " + self.target_address + "...") try: #Connect to sphero and populate services and characteristics self.peripheral = btle.Peripheral(self.target_address, addrType=btle.ADDR_TYPE_RANDOM) sys.stdout.write("Connected!\nFinding services...") sys.stdout.flush() self.peripheral.getServices() self.ble_service = self.peripheral.getServiceByUUID( btle.UUID(self.UUIDs['BLE_SVC'])) self.anti_dos_characteristic = self.ble_service.getCharacteristics( self.UUIDs['ANTI_DOS_CHAR'])[0] self.robot_control_service = self.peripheral.getServiceByUUID( self.UUIDs['BOT_CTRL_SVC']) self.wake_characteristic = self.ble_service.getCharacteristics( self.UUIDs['WAKE_CHAR'])[0] self.tx_power_characteristic = self.ble_service.getCharacteristics( self.UUIDs['TX_PWR_CHAR'])[0] self.anti_dos_characteristic = self.ble_service.getCharacteristics( self.UUIDs['ANTI_DOS_CHAR'])[0] self.commands_characteristic = self.robot_control_service.getCharacteristics( self.UUIDs['CMD_CHAR'])[0] self.response_characteristic = self.robot_control_service.getCharacteristics( self.UUIDs['RESP_CHAR'])[0] sys.stdout.write("Services found!\nEnabling dev mode...") sys.stdout.flush() self._enable_dev_mode() except btle.BTLEException as error: sys.stdout.write(error.strerror) sys.stdout.flush() time.sleep(5.0) sys.exit(1) sys.stdout.write("Done.\n") sys.stdout.flush() return True
"device": "TokenCube 1", "addr": "dc:00:62:95:62:67", "type": "ambient" } } INFLUX_SERVER = os.environ.get("INFLUX_SERVER", None) or "raspberrypi.local" INFLUX_DATABASE = os.environ.get("INFLUX_DB", None) or "sensors" INFLUX_USER = os.environ.get("INFLUX_USER", None) or "root" INFLUX_PASSWORD = os.environ.get("INFLUX_PASSWORD", None) or "root" if __name__ == "__main__": print "Creating Scanner" delegate = DeviceForwardingDelegate() delegate.handlers.append(IGrillHandler(device_settings)) delegate.handlers.append(TokenCubeHandler(device_settings)) scanner = Scanner() scanner.withDelegate(delegate) print "Connecting to InfluxDB server" persistence = DataPersistence(INFLUX_SERVER, INFLUX_DATABASE, INFLUX_USER, INFLUX_PASSWORD) while True: print "Scanning..." scanner.scan(30) print "Persisting..." for handler in delegate.handlers: handler.persist_stats(persistence)
class CarControl: scanner = None devices = [] devicetext = "" isConnected = False carAddr = None carName = None carDevice = None carPeripheral = None def __repr__(self): return "devices: {}, address: {}, carName: {}".format( len(self.devices), self.carAddr, self.carName) #return "devices: {}".format(len(self.devices)) def scan(self, timeout=10): foundDevices = 0 self.devices = [] self.devicetext = "" newdevices = [] scansuccess = False try: self.scanner = Scanner() self.scanner.withDelegate(MainDelegate()) newdevices = self.scanner.scan(timeout) scansuccess = True except Exception as e: scansuccess = False if scansuccess: for dev in newdevices: if dev.addrType == btle.ADDR_TYPE_PUBLIC: foundDevices = foundDevices + 1 self.devices.append({ "name": dev.getValueText(9), "addr": dev.addr }) self.devicetext = self.devicetext + "> Device #{} {} ({}), [{}], [{}]\n".format( foundDevices, dev.addr, dev.addrType, dev.getValueText(9), dev.getValueText(8)) # add known cars for k in KNOWN_CARS: foundDevices = foundDevices + 1 self.devices.append({"name": k["name"], "addr": k["addr"]}) self.devicetext = self.devicetext + "> Device #{} {} ({}), [{}]\n".format( foundDevices, k["addr"], "Known Device", k["name"]) return scansuccess def connect(self, carnum): if len(self.devices) == 0: print("connect: Nothing scanned") return if carnum < 0 or carnum > len(self.devices): print("connect: Car number invalid, {}".format(carnum)) return try: self.carAddr = self.devices[carnum]["addr"] self.carName = self.devices[carnum]["name"] self.carPeripheral = Peripheral() self.carPeripheral.withDelegate(MainDelegate()) self.carPeripheral.connect(self.carAddr) self.isConnected = True return True except Exception as e: self.carPeripheral = None print("connect: Error,", e) return False def listdescriptors(self): try: print("listdescriptors: ...") print("listdescriptors: listing descriptors") descriptors = self.carPeripheral.getDescriptors() for desc in descriptors: print(" -- DESCRIPTORS: {}, [{}], Handle: {} (0x{:04x})". format(desc.uuid, UUID(desc.uuid).getCommonName(), desc.handle, desc.handle)) except Exception as e: print("listdescriptors: Error,", e) def listservices(self): try: print("listservices: listing services") services = self.carPeripheral.getServices() for serv in services: print(" -- SERVICE: {} [{}]".format( serv.uuid, UUID(serv.uuid).getCommonName())) characteristics = serv.getCharacteristics() for chara in characteristics: print( " -- --> CHAR: {}, Handle: {} (0x{:04x}) - {} - [{}]" .format(chara.uuid, chara.getHandle(), chara.getHandle(), chara.propertiesToString(), UUID(chara.uuid).getCommonName())) except Exception as e: print("listservices: Error,", e) def disconnectcar(self): self.isConnected = False if self.carPeripheral is None: print("disconnectcar: No car connected") return False try: self.carPeripheral.disconnect() self.carPeripheral = None return True except Exception as e: print("disconnectcar: Error,", e) return False def readcharacteristics(self): try: if self.carPeripheral is None: print("readcharacteristics: No car connected") return print("readcharacteristics: reading the readables") chars = self.carPeripheral.getCharacteristics() for c in chars: if c.supportsRead(): print( " -- READ: {} [{}] (0x{:04x}), {}, Value: {}".format( c.uuid, UUID(c.uuid).getCommonName(), c.getHandle(), c.descs, c.read() if c.supportsRead() else "")) except Exception as e: print("readcharacteristics: Error,", e) def writevalue(self, handle, value, wait=False): try: if self.carPeripheral is None: #print("writevalue: No car connected") return #print("writevalue: writing to handle 0x{:04x} value {}".format(handle, value)) self.carPeripheral.writeCharacteristic(handle, value, wait) except Exception as e: print("writevalue: Error,", e) def readvalue(self, handle): try: if self.carPeripheral is None: print("readvalue: No car connected") return print("readvalue: reading handle 0x{:04x}".format(handle)) value = self.carPeripheral.readCharacteristic(handle) print("readvalue: Handle 0x{:04x} = {}".format(handle, value)) except Exception as e: print("readvalue: Error,", e) def sendhandshake(self): # handshake... for finger in BTCMD_HANDSHAKE: self.writevalue(BTDRIVE_HANDLE, finger, True) def carfiregun(self, intensity=0.5): self.writevalue(BTDRIVE_HANDLE, BTCMD_FIREGUN) def carforward(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x00 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, actual_intensity, 0x00] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True) def carreverse(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x20 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, actual_intensity, 0x00] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True) def carright(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x40 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, 0x00, actual_intensity] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True) def carleft(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x60 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, 0x00, actual_intensity] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True)
def start(self, notify): scanner = Scanner() scanner.withDelegate(ScanDelegate(scanner, notify)) scanner.scan(10.0)
def main(): sc = Scanner() scd = MiBand2ScanDelegate() sc.withDelegate(scd) scan_thread = threading.Thread(target=scan_miband2, args=(sc,)) scan_thread.start() for i in range(max_connections): t = threading.Thread(target=worker) t.daemon = True t.start() while True: try: s = raw_input('> ') except: break try: command = s.strip().lower() if command == "exit": scan_thread.do_scan = False scan_thread.join() print ("Disconnecting from %s devices" % len(connected_devices.values())) for con in connected_devices.values(): con.disconnect() print("Saving changes to Registered Devices storage") save_registered(registered_devices, devices_last_sync) break elif command == "save": print("Saving changes to Registered Devices storage") save_registered(registered_devices, devices_last_sync) elif command == "devices": mibands = scd.tmp_devices for idx,mb in enumerate(mibands.keys()): str = "[%s] Mi Band 2 (%s) %sdB " % (idx,mb,mibands[mibands.keys()[idx]].rssi) if mb in registered_devices: str += "[R]" if mb in connected_devices: str += "[C]" print str elif "alert" in command: arg = re.search("\w+\s+(\d+)\s+(\d+)", command) if arg != None and len(arg.groups()) == 2: dev_id = int(arg.groups()[0]) alert_int = int(arg.groups()[1]) if mibands.keys()[dev_id] in registered_devices: if mibands.keys()[dev_id] in connected_devices.keys(): try: mb2 = connected_devices[mibands.keys()[dev_id]] data = struct.pack('B', alert_int) mb2.send_alert(data) print "Sending Notification: " + binascii.hexlify(data) except BTLEException: print("There was a problem alerting this MiBand2, try again later") else: print("That MiBand2 is not connected!") else: print("That MiBand2 is not registered") else: print("'alert' takes two parameters") elif "unregister" in command: arg = re.search("\w+\s+(\d+)", command) if arg != None and len(arg.groups()) == 1: dev_id = int(arg.groups()[0]) if mibands.keys()[dev_id] in registered_devices: if not mibands.keys()[dev_id] in connected_devices.values(): try: registered_devices.remove(mibands.keys()[dev_id]) print("MiBand2 unregistered!") except BTLEException: print("There was a problem unregistering this MiBand2, try again later") else: print("Disconnect the miBand2 first!") else: print("That MiBand2 is not registered") else: print("'unregister' takes only one parameter") elif "register" in command: arg = re.search("\w+\s+(\d+)", command) if arg != None and len(arg.groups()) == 1: dev_id = int(arg.groups()[0]) if mibands.keys()[dev_id] in registered_devices: print("That MiBand2 is already registered") else: try: mb2 = MiBand2(mibands.keys()[dev_id], initialize=True) registered_devices.append(mibands.keys()[dev_id]) except BTLEException as e: print("There was a problem disconnecting this MiBand2, try again later") print e else: print("'register' takes only one parameter") elif "disconnect" in command: arg = re.search("\w+\s+(\d+)", command) if arg != None and len(arg.groups()) == 1: dev_id = int(arg.groups()[0]) if len(connected_devices.keys()) >= max_connections: print("Can't connect to more than 5 devices at the same time, disconnect some") else: if mibands.keys()[dev_id] in connected_devices.keys(): try: mb2 = connected_devices[mibands.keys()[dev_id]] mb2.disconnect() del connected_devices[mibands.keys()[dev_id]] del mb2 print ("MiBand2 disconnected!") except BTLEException as e: print("There was a problem disconnecting this MiBand2, try again later") print e else: print("That MiBand2 isn't connected!") else: print("'connect' takes only one parameter") elif "connect" in command: arg = re.search("\w+\s+(\d+)", command) if arg != None and len(arg.groups()) == 1: dev_id = int(arg.groups()[0]) if len(connected_devices.keys()) >= 5: print("Can't connect to more than 5 devices at the same time, disconnect some") else: if mibands.keys()[dev_id] in registered_devices: if mibands.keys()[dev_id] in connected_devices.keys(): print("That MiBand2 is already connected") else: try: mb2 = MiBand2(mibands.keys()[dev_id], initialize=False) connected_devices[mibands.keys()[dev_id]] = mb2 except BTLEException as e: print("There was a problem connecting to this MiBand2, try again later") print e else: print("You have to register the MiBand2 before connecting to it") else: print("'connect' takes only one parameter") elif "alarms" in command: pass # TODO: load JSON alarms into device representation # let the user view, queue, toggle and toggle days of each alarm # save and persist alarms in JSON form, key should be mac # and elements arrays of alarm parameters (hour, min, enabledness and daymasks) elif "activity" in command: arg = re.search("\w+\s+(\w+)", command) if arg != None and len(arg.groups()) == 1: if arg.groups()[0] == 'all': print("Fetching all registered and in range Miband2's activity data") # Check that the registered device is present on the scanned mibands list for item in filter(lambda x: x in registered_devices, mibands.keys()): q.put(item) else: dev_id = int(arg.groups()[0]) if mibands.keys()[dev_id] in registered_devices: q.put(mibands.keys()[dev_id]) else: print("MiBand2 should be registered before fetching activity data") else: print("'activity' takes only one parameter") elif command == '': pass else: print ("Unknown command %s, try using 'help'" % command) except OSError: print 'Invalid command'