def _process_packet(data): ev = aiobs.HCI_Event() xx = ev.decode(data) xx = EddyStone().decode(ev) if xx: if xx['url'][:24] == 'https://wilshireliu.com/': #print("Google beacon: {}".format(xx['url'][:24])) print("Steps: {}".format(xx['url'][24:])) global actualsteps actualsteps = int(xx['url'][24:]) * 1000 print("actual steps:", actualsteps) print("today goal:", today_goal) print("tomorrow goal:", tmr_goal) client = mqtt.Client("P1") client.on_message = on_message client.connect(broker_address) client.loop_start() client.subscribe(subscribetopic) time.sleep(3) if actualsteps < today_goal: message_goal = "GET UP!" client.publish( publishtopic, "Friend, the world is so beautiful so go outside and explore the world. Btw the goal of tomorrow is {}" .format(tmr_goal)) client.loop_stop() if actualsteps >= today_goal: message_goal = "GREAT JOB! You beat your goal" print(today_goal) client.publish( publishtopic, "Nice! You beat the goal and the goal of tomorrow is {}". format(tmr_goal)) client.loop_stop()
def my_process(data): global opts ev = aiobs.HCI_Event() xx = ev.decode(data) if opts.mac: goon = False mac = ev.retrieve("peer") for x in mac: if x.val in opts.mac: goon = True break if not goon: return if opts.raw: print("Raw data: {}".format(ev.raw_data)) if opts.eddy: xx = EddyStone().decode(ev) if xx: print("Google Beacon {}".format(xx)) elif opts.ruuvi: xx = RuuviWeather().decode(ev) if xx: print("Weather info {}".format(xx)) elif opts.pebble: xx = BlueMaestro().decode(ev) if xx: print("Pebble info {}".format(xx)) elif opts.atcmi: xx = ATCMiThermometer().decode(ev) if xx: print("Temperature info {}".format(xx)) else: ev.show(0)
def _process_packet(data): global steps ev = aiobs.HCI_Event() # event is passed to HCI in between the BT controller and host stack xx = ev.decode(data) # decode the signal xx = EddyStone().decode(ev) # run our decoded packet through the EddyStone protocol if xx: match = re.match(r'.*(group3p).*steps=(\d*).*', xx['url']) # if we match, we parse the steps and publish it to the broker if match: print('Received Eddystone Beacon Steps. Processing...') today = datetime.datetime.now().date() steps = int(match.groups()[1]) print('Publishing steps...') client.publish(publish_topic, _determine_goal_met()) with open(history_file, 'r') as inf: lines = inf.read().strip() with open(history_file, 'w') as outf: new_entry = '{},{},{}'.format(str(today),steps,goal) found = False for line in lines.split('\n'): line = line.strip() entry = [item.strip() for item in line.split(',')] if entry[0] == str(today): found = True outf.write(new_entry) else: outf.write(line) outf.write('\n') if not found: outf.write(new_entry)
def my_process(data): global opts ev = aiobs.HCI_Event() xx = ev.decode(data) if opts.mac: goon = False mac = ev.retrieve("peer") for x in mac: if x.val in opts.mac: goon = True break if not goon: return if opts.raw: print("Raw data: {}".format(ev.raw_data)) if opts.eddy: xx = EddyStone().decode(ev) if xx: print("Google Beacon {}".format(xx)) elif opts.ruuvi: xx = RuuviWeather().decode(ev) if xx: print("Weather info {}".format(xx)) elif opts.bbw200: xx = Bbw200().decode(ev) if xx: print("{}".format(xx)) else: ev.show(0)
def _process_packet(data): ev = aiobs.HCI_Event() xx = ev.decode(data) xx = EddyStone().decode(ev) if xx: if xx['url'][:24] == 'https://wilshireliu.com/': #print("Google beacon: {}".format(xx['url'][:24])) print("Steps: {}".format(xx['url'][24:])) global actualsteps actualsteps = int(xx['url'][24:]) #*1000 print("actual steps:", actualsteps) print("today goal:", today_goal) print("tomorrow goal:", tmr_goal) client = mqtt.Client("P1") client.on_message = on_message client.connect(broker_address) client.loop_start() client.subscribe(subscribetopic) time.sleep(3) if actualsteps < today_goal: #client.publish(publishtopic, "You have only walked " + str(actualsteps) + " steps. You need to walk " + str(today_goal) + " steps.") client.publish( publishtopic, "{\"actualSteps\": " + str(actualsteps) + ", \"todayGoal\": " + str(today_goal) + "}") client.loop_stop() if actualsteps >= today_goal: print(today_goal) client.publish( publishtopic, "Nice! You beat the goal for today and the goal for tomorrow is {}" .format(tmr_goal)) client.loop_stop()
def _process_packet(data): ev = aiobs.HCI_Event() xx = ev.decode(data) xx = EddyStone().decode(ev) if xx: if "team8" in xx['url']: value = format(xx['url'][13:21]) print(value) print("sending pulication") client.publish(publishtopic, value)
def _process_packet(data): ev=aiobs.HCI_Event() xx = ev.decode(data) xx = EddyStone().decode(ev) if xx: if (xx['url'][:24] == "https://IoTexasSteps.com"): numOfSteps = xx['url'][25:] stepMessage = "IoTaxes steps:{}".format(numOfSteps) saveSteps(numOfSteps) print(stepMessage) event_loop.stop() btctrl.stop_scan_request()
def my_process(data): global current_x global current_y global direction global time_for_segment global current_segment_time global number_of_measurements_this_segment ev = aiobs.HCI_Event() xx = ev.decode(data) #print(xx) #return beacon = EddyStone().decode(ev) if beacon: #print("Google Beacon {}".format(beacon)) rssi = beacon['rssi'] #print(rssi) rssi_measurements[current_y][current_x] += rssi number_of_measurements_this_segment += 1 # TODO SAVE RSSI if time.time() - current_segment_time > time_for_segment: print('MOVE') for i in range(0, 6): os.system('echo 1 >/sys/class/leds/led0/brightness') time.sleep(0.1) os.system('echo 0 >/sys/class/leds/led0/brightness') time.sleep(0.1) rssi_measurements[current_y][ current_x] /= number_of_measurements_this_segment number_of_measurements_this_segment = 0 current_x += direction if current_x == -1 or current_x == x_dim: current_x -= direction direction *= -1 current_y += 1 current_segment_time = time.time() print('moving to sector', current_x, current_y) if current_y == y_dim: print('ALL DONE') np.savetxt("foo.csv", rssi_measurements, delimiter=",") exit(0)
def test_eddystone_url(self): pckt = aioblescan.HCI_Event() pckt.decode( b'\x04>)\x02\x01\x03\x01\xdc)e\x90U\xf1\x1d\x02\x01\x06\x03\x03\xaa\xfe\x15\x16\xaa\xfe\x10\xf6\x03makecode\x00#about\xb5' ) result = EddyStone().decode(pckt) self.assertDictEqual( result, { 'mac address': 'f1:55:90:65:29:dc', 'tx_power': -10, 'url': 'https://makecode.com/#about', 'rssi': -75 })
def _process_packet(data): ev = aiobs.HCI_Event() xx = ev.decode(data) xx = EddyStone().decode(ev) if xx: if "http://cmd?" in xx['url']: global step_count step_count = xx['url'][11:] print(step_count) client.loop_start() client.subscribe(subscribetopic) time.sleep(4) client.loop_stop()
def test_eddystone_uid(self): pckt = aioblescan.HCI_Event() pckt.decode( b'\x04>)\x02\x01\x03\x01\xdc)e\x90U\xf1\x1d\x02\x01\x06\x03\x03\xaa\xfe\x15\x16\xaa\xfe\x00\xf6\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00X\xb6' ) result = EddyStone().decode(pckt) self.assertDictEqual( result, { 'tx_power': -10, 'rssi': -74, 'name space': (0x63).to_bytes(10, byteorder="big"), 'instance': (0x58).to_bytes(6, byteorder="big"), 'mac address': 'f1:55:90:65:29:dc' })
def _process_packet(data): """ Filter BLE packets to only show Eddystone data before calling packet_callback :param data: BLE Packet data :return: None """ logging.debug('Packet found') ev = aioblescan.HCI_Event() ev.decode(data) logging.debug('Using the following callback %s', packet_callback) if packet_callback is not None: eddystone_data = EddyStone().decode(ev) if eddystone_data: packet_callback(eddystone_data)
def test_eddystone_url(self): pckt = aioblescan.HCI_Event() pckt.decode( b"\x04>)\x02\x01\x03\x01\xdc)e\x90U\xf1\x1d\x02\x01\x06\x03\x03\xaa\xfe\x15\x16\xaa\xfe\x10\xf6\x03makecode\x00#about\xb5" ) result = EddyStone().decode(pckt) self.assertDictEqual( result, { "mac address": "f1:55:90:65:29:dc", "tx_power": -10, "url": "https://makecode.com/#about", "rssi": -75, }, )
def test_eddystone_uid(self): pckt = aioblescan.HCI_Event() pckt.decode( b"\x04>)\x02\x01\x03\x01\xdc)e\x90U\xf1\x1d\x02\x01\x06\x03\x03\xaa\xfe\x15\x16\xaa\xfe\x00\xf6\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00X\xb6" ) result = EddyStone().decode(pckt) self.assertDictEqual( result, { "tx_power": -10, "rssi": -74, "name space": (0x63).to_bytes(10, byteorder="big"), "instance": (0x58).to_bytes(6, byteorder="big"), "mac address": "f1:55:90:65:29:dc", }, )
def _process_packet(data): #global val ev = aiobs.HCI_Event() xx = ev.decode(data) xx = EddyStone().decode(ev) if xx is not None: check = xx['url'] if 'werock' in str(xx['url']): val = xx['url'][26:] print("{}".format(xx['url'][26:])) client.on_message = on_message client.loop_start() client.subscribe(subscribetopic) client.publish(publishtopic, val) #time.sleep(10) client.loop_stop()
#create a connection with the raw socket #This used to work but now requires a STREAM socket. #fac=event_loop.create_connection(aiobs.BLEScanRequester,sock=mysocket) #Thanks to martensjacobs for this fix fac=event_loop._create_connection_transport(mysocket,aiobs.BLEScanRequester,None,None) #Start it conn,btctrl = event_loop.run_until_complete(fac) #Attach your processing btctrl.process=my_process if opts.advertise: command = aiobs.HCI_Cmd_LE_Advertise(enable=False) btctrl.send_command(command) command = aiobs.HCI_Cmd_LE_Set_Advertised_Params(interval_min=opts.advertise,interval_max=opts.advertise) btctrl.send_command(command) command = aiobs.HCI_Cmd_LE_Set_Advertised_Msg(msg=EddyStone()) btctrl.send_command(command) command = aiobs.HCI_Cmd_LE_Advertise(enable=True) btctrl.send_command(command) #Probe btctrl.send_scan_request() try: # event_loop.run_until_complete(coro) event_loop.run_forever() except KeyboardInterrupt: print('keyboard interrupt') finally: print('closing event loop') btctrl.stop_scan_request() command = aiobs.HCI_Cmd_LE_Advertise(enable=False)
#fac=event_loop.create_connection(aiobs.BLEScanRequester,sock=mysocket) #Thanks to martensjacobs for this fix fac = event_loop._create_connection_transport(mysocket, aiobs.BLEScanRequester, None, None) #Start it conn, btctrl = event_loop.run_until_complete(fac) #Attach your processing btctrl.process = my_process if opts.advertise: command = aiobs.HCI_Cmd_LE_Advertise(enable=False) btctrl.send_command(command) command = aiobs.HCI_Cmd_LE_Set_Advertised_Params( interval_min=opts.advertise, interval_max=opts.advertise) btctrl.send_command(command) if opts.url: myeddy = EddyStone(param=opts.url) else: myeddy = EddyStone() if opts.txpower: myeddy.power = opts.txpower command = aiobs.HCI_Cmd_LE_Set_Advertised_Msg(msg=myeddy) btctrl.send_command(command) command = aiobs.HCI_Cmd_LE_Advertise(enable=True) btctrl.send_command(command) #Probe btctrl.send_scan_request() try: # event_loop.run_until_complete(coro) event_loop.run_forever() except KeyboardInterrupt:
def decode(self, packet): #Look for Ruuvi tag URL and decode it result = {} url = EddyStone().decode(packet) if url is None: url = packet.retrieve("Payload for mfg_specific_data") if url: val = url[0].val if val[0] == 0x99 and val[1] == 0x04 and val[2] == 0x03: #Looks just right result["mac address"] = packet.retrieve("peer")[0].val val = val[2:] result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] result["temperature"] += val[3] / 100.0 result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 dx = int.from_bytes(val[6:8], "big", signed=True) dy = int.from_bytes(val[8:10], "big", signed=True) dz = int.from_bytes(val[10:12], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = int.from_bytes(val[12:14], "big") return result else: return None rssi = packet.retrieve("rssi") if rssi: result["rssi"] = rssi[-1].val power = packet.retrieve("tx_power") if power: result["tx_power"] = power[-1].val try: if "//ruu.vi/" in url["url"]: #We got a live one result["mac address"] = packet.retrieve("peer")[0].val url = url["url"].split("//ruu.vi/#")[-1] if len(url) > 8: url = url[:-1] val = b64decode(url + '=' * (4 - len(url) % 4), "#.") if val[0] in [2, 4]: result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] #Signed int... result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 if val[0] == 4: try: result["id"] = val[6] except: pass return result elif val[0] == 3: result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] result["temperature"] += val[3] / 100.0 result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 dx = int.from_bytes(val[6:8], "big", signed=True) dy = int.from_bytes(val[8:10], "big", signed=True) dz = int.from_bytes(val[10:12], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = int.from_bytes(val[12:14], "big") return result except: print("\n\nurl oops....") packet.show() return None
class Decoder: all_decoders = { "pebble": BlueMaestro().decode, "ruuviraw": RuuviTagRaw().decode, "ruuviurl": RuuviTagUrl().decode, "eddy": EddyStone().decode, } def __init__(self): self.use_fixed_decoders = False self.fixed_decoders = [] self.mac_decoders = {} def enable_fixed_decoders(self, decoders=[]): # if enabled, uses fixed decoders-list self.use_fixed_decoders = True print("Setting fixed_decoders = {}".format(decoders)) if "all" in decoders: self.fixed_decoders = list(self.all_decoders.keys()) else: self.fixed_decoders = decoders def enable_per_mac_decoders(self, sources=[]): # Enable per mac decoders as defined in sources configuration self.use_fixed_decoders = False print("Setting per_mac_decoders = {}".format(sources)) for mac, mac_config in sources.items(): _d = mac_config.get("decoders", []) if "all" in _d: self.mac_decoders[mac] = list(self.all_decoders.keys()) else: self.mac_decoders[mac] = _d def get_decoders(self, mac): if self.use_fixed_decoders: return self.fixed_decoders else: if mac in self.mac_decoders: return self.mac_decoders.get(mac) else: return self.mac_decoders.get("*", None) def run(self, data, simulator=0): if simulator > 0: # data is from BLE simulator, just return the data return data base_mesg = {"decoder": "none"} ev = aiobs.HCI_Event() ev.decode(data) mesg = packet_info(ev) if "mac" not in mesg: # invalid packet if no mac (peer) address print("Decoder: invalid message, no mac.") return base_mesg decoders = self.get_decoders(mesg["mac"]) if not decoders: return base_mesg # Try actually decode the message for decoder in decoders: func = self.all_decoders.get(decoder, None) if func: mesg.update(func(ev)) if mesg: mesg["decoder"] = decoder return {**base_mesg, **mesg} return base_mesg
def decode(self, packet): # Look for Ruuvi tag URL and decode it result = {} rssi = packet.retrieve("rssi") if rssi: result["rssi"] = rssi[-1].val url = EddyStone().decode(packet) if url is None: data = packet.retrieve("Manufacturer Specific Data") if data: val = data[0].payload if val[0].val == 0x0499: val = val[1].val if val[0] == 0x03: # print("RAWv1") # Looks just right RAWv1 result["mac address"] = packet.retrieve("peer")[0].val result["humidity"] = val[1] / 2.0 result["temperature"] = get_temp(val[2], val[3]) result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 dx = int.from_bytes(val[6:8], "big", signed=True) dy = int.from_bytes(val[8:10], "big", signed=True) dz = int.from_bytes(val[10:12], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = int.from_bytes(val[12:14], "big") return result elif val[0] == 0x05: # print("RAWv2") result["mac address"] = packet.retrieve("peer")[0].val result["temperature"] = ( int.from_bytes(val[1:3], "big", signed=True) * 0.005) result["humidity"] = int.from_bytes(val[3:5], "big") * 0.0025 result["pressure"] = (int.from_bytes(val[5:7], "big") + 50000) / 100.0 dx = int.from_bytes(val[7:9], "big", signed=True) dy = int.from_bytes(val[9:11], "big", signed=True) dz = int.from_bytes(val[11:13], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = ( int.from_bytes(val[13:15], "big") >> 5) + 1600 result["tx_power"] = ( int.from_bytes(val[13:15], "big") & 0x1F) * 2 - 40 result["move count"] = val[15] result["sequence"] = int.from_bytes(val[16:18], "big") return result else: # packet.show() return None else: # print("No data") return None else: # print("URL") power = packet.retrieve("tx_power") if power: result["tx_power"] = power[-1].val try: if "//ruu.vi/" in url["url"]: # We got a live one result["mac address"] = packet.retrieve("peer")[0].val url = url["url"].split("//ruu.vi/#")[-1] if len(url) > 8: url = url[:-1] val = b64decode(url + "=" * (4 - len(url) % 4), "#.") if val[0] in [2, 4]: result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] # Signed int... result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 if val[0] == 4: try: result["id"] = val[6] except: pass return result elif val[0] == 3: result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] result["temperature"] += val[3] / 100.0 result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 dx = int.from_bytes(val[6:8], "big", signed=True) dy = int.from_bytes(val[8:10], "big", signed=True) dz = int.from_bytes(val[10:12], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = int.from_bytes(val[12:14], "big") return result except: pass # print ("\n\nurl oops....") # packet.show() return None
def main(args=None): global opts parser = argparse.ArgumentParser( description="Track BLE advertised packets") parser.add_argument( "-e", "--eddy", action="store_true", default=False, help="Look specificaly for Eddystone messages.", ) parser.add_argument( "-m", "--mac", type=check_mac, action="append", help="Look for these MAC addresses.", ) parser.add_argument( "-r", "--ruuvi", action="store_true", default=False, help="Look only for Ruuvi tag Weather station messages", ) parser.add_argument( "-p", "--pebble", action="store_true", default=False, help="Look only for Pebble Environment Monitor", ) parser.add_argument( "-A", "--atcmi", action="store_true", default=False, help="Look only for ATC_MiThermometer tag messages", ) parser.add_argument( "-R", "--raw", action="store_true", default=False, help="Also show the raw data.", ) parser.add_argument( "-a", "--advertise", type=int, default=0, help= "Broadcast like an EddyStone Beacon. Set the interval between packet in millisec", ) parser.add_argument( "-u", "--url", type=str, default="", help="When broadcasting like an EddyStone Beacon, set the url.", ) parser.add_argument( "-t", "--txpower", type=int, default=0, help="When broadcasting like an EddyStone Beacon, set the Tx power", ) parser.add_argument( "-D", "--device", type=int, default=0, help="Select the hciX device to use (default 0, i.e. hci0).", ) try: opts = parser.parse_args() except Exception as e: parser.error("Error: " + str(e)) sys.exit() event_loop = asyncio.get_event_loop() # First create and configure a raw socket mysocket = aiobs.create_bt_socket(opts.device) # create a connection with the raw socket # This used to work but now requires a STREAM socket. # fac=event_loop.create_connection(aiobs.BLEScanRequester,sock=mysocket) # Thanks to martensjacobs for this fix fac = event_loop._create_connection_transport(mysocket, aiobs.BLEScanRequester, None, None) # Start it conn, btctrl = event_loop.run_until_complete(fac) # Attach your processing btctrl.process = my_process if opts.advertise: command = aiobs.HCI_Cmd_LE_Advertise(enable=False) event_loop.run_until_complete(btctrl.send_command(command)) command = aiobs.HCI_Cmd_LE_Set_Advertised_Params( interval_min=opts.advertise, interval_max=opts.advertise) event_loop.run_until_complete(btctrl.send_command(command)) if opts.url: myeddy = EddyStone(param=opts.url) else: myeddy = EddyStone() if opts.txpower: myeddy.power = opts.txpower command = aiobs.HCI_Cmd_LE_Set_Advertised_Msg(msg=myeddy) event_loop.run_until_complete(btctrl.send_command(command)) command = aiobs.HCI_Cmd_LE_Advertise(enable=True) event_loop.run_until_complete(btctrl.send_command(command)) # Probe event_loop.run_until_complete(btctrl.send_scan_request()) try: # event_loop.run_until_complete(coro) event_loop.run_forever() except KeyboardInterrupt: print("keyboard interrupt") finally: print("closing event loop") event_loop.run_until_complete(btctrl.stop_scan_request()) command = aiobs.HCI_Cmd_LE_Advertise(enable=False) event_loop.run_until_complete(btctrl.send_command(command)) conn.close() event_loop.close()
def decode(self, packet): #Look for Ruuvi tag URL and decode it result = {} rssi = packet.retrieve("rssi") if rssi: result["rssi"] = rssi[-1].val url = EddyStone().decode(packet) if url is None: url = packet.retrieve("Payload for mfg_specific_data") if url: val = url[0].val if val[0] == 0x99 and val[1] == 0x04 and val[2] == 0x03: #Looks just right result["mac address"] = packet.retrieve("peer")[0].val val = val[2:] result["humidity"] = val[1] / 2.0 result["temperature"] = s8(val[2]) result["temperature"] += val[3] / 100.0 result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 dx = int.from_bytes(val[6:8], "big", signed=True) dy = int.from_bytes(val[8:10], "big", signed=True) dz = int.from_bytes(val[10:12], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = int.from_bytes(val[12:14], "big") return result elif val[0] == 0x99 and val[1] == 0x04 and val[2] == 0x05: #Looks just right result["mac address"] = packet.retrieve("peer")[0].val val = val[2:] result["temperature"] = "{:.1f}".format( int.from_bytes(val[1:3], "big", signed=True) * 0.005) result["humidity"] = "{:.1f}".format( int.from_bytes(val[3:5], "big") * 0.0025) result["pressure"] = int.from_bytes(val[5:7], "big") + 50000 dx = int.from_bytes(val[7:9], "big", signed=True) dy = int.from_bytes(val[9:11], "big", signed=True) dz = int.from_bytes(val[11:13], "big", signed=True) length = "{:.1f}".format(sqrt(dx**2 + dy**2 + dz**2)) result["accelerometer"] = (dx, dy, dz, length) p = int.from_bytes(val[13:15], "big") result["voltage"] = 1600 + ( p >> (16 - 11) ) #power bat (1st 11bits (so shift 5 places right) of p (unsigned) mV over 1600) (1.6V to 3.647V range) result["tx"] = -40 + ( (p & 31) * 2 ) #power tx (last 5 bits (31 = 11111 for bitwise and) of p (unsigned) dBm over -40 in 2dBm steps (-40 - +24) result["movement"] = val[15] result["sequence"] = int.from_bytes(val[16:18], "big") #result["payloadmac"]=val[18:24] #FIXME(maybe, for completeness) return result elif val[0] == 0x99 and val[1] == 0x04: #BLE Manufacturer specific data + Ruuvi manufacturer ID #But not a known data/packet type. print("DEBUG: Unknown Ruuvi Data Format") return None else: # print("DEBUG: Unknown BLE Manufacturer specific data") return None else: return None power = packet.retrieve("tx_power") if power: result["tx_power"] = power[-1].val try: if "//ruu.vi/" in url["url"]: #We got a live one result["mac address"] = packet.retrieve("peer")[0].val url = url["url"].split("//ruu.vi/#")[-1] if len(url) > 8: url = url[:-1] val = b64decode(url + '=' * (4 - len(url) % 4), "#.") if val[0] in [2, 4]: result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] #Signed int... result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 if val[0] == 4: try: result["id"] = val[6] except: pass return result elif val[0] == 3: result["humidity"] = val[1] / 2.0 result["temperature"] = unpack( ">b", int(val[2]).to_bytes(1, "big"))[0] result["temperature"] += val[3] / 100.0 result["pressure"] = int.from_bytes(val[4:6], "big") + 50000 dx = int.from_bytes(val[6:8], "big", signed=True) dy = int.from_bytes(val[8:10], "big", signed=True) dz = int.from_bytes(val[10:12], "big", signed=True) length = sqrt(dx**2 + dy**2 + dz**2) result["accelerometer"] = (dx, dy, dz, length) result["voltage"] = int.from_bytes(val[12:14], "big") return result except: print("\n\nurl oops....") packet.show() return None