def url_encoder(self): encodedurl = [] encodedurl.append(aios.IntByte("Tx Power", self.power)) asisurl = "" myurl = urlparse(self.type_payload) myhostname = myurl.hostname mypath = myurl.path if (myurl.scheme, myhostname.startswith("www.")) in url_schemes: encodedurl.append( aios.IntByte( "URL Scheme", url_schemes.index( (myurl.scheme, myhostname.startswith("www."))), )) if myhostname.startswith("www."): myhostname = myhostname[4:] extval = None if myhostname.split(".")[-1] in url_domain: extval = url_domain.index(myhostname.split(".")[-1]) myhostname = ".".join(myhostname.split(".")[:-1]) if extval is not None and not mypath.startswith("/"): extval += 7 else: if myurl.port is None: if extval is not None: mypath = mypath[1:] else: extval += 7 encodedurl.append(aios.String("URL string")) encodedurl[-1].val = myhostname if extval is not None: encodedurl.append(aios.IntByte("URL Extention", extval)) if myurl.port: asisurl += ":" + str(myurl.port) + mypath asisurl += mypath if myurl.params: asisurl += ";" + myurl.params if myurl.query: asisurl += "?" + myurl.query if myurl.fragment: asisurl += "#" + myurl.fragment encodedurl.append(aios.String("Rest of URL")) encodedurl[-1].val = asisurl tlength = 0 for x in encodedurl: # Check the payload length tlength += len(x) if tlength > 19: # Actually 18 but we have tx power raise Exception("Encoded url too long (max 18 bytes)") self.service_data_length.val += tlength # Update the payload length return encodedurl
def __init__(self, type=ESType.url, param="https://goo.gl/m9UiEA"): self.power = 0 self.payload = ( [] ) # As defined in https://github.com/google/eddystone/blob/master/protocol-specification.md self.payload.append(aios.Byte("Flag Length", b"\x02")) self.payload.append(aios.Byte("Flag Data Type", b"\x01")) self.payload.append(aios.Byte("Flag Data", b"\x1a")) self.payload.append(aios.Byte("Length UUID services", b"\x03")) self.payload.append(aios.Byte("Complete List UUID Service", b"\x03")) self.payload.append(aios.Byte("Eddystone UUID", b"\xaa")) self.payload.append(aios.Byte("...", b"\xfe")) self.service_data_length = aios.IntByte("Service Data length", 4) self.payload.append(self.service_data_length) self.payload.append(aios.Byte("Service Data data type value", b"\x16")) self.payload.append(aios.Byte("Eddystone UUID", b"\xaa")) self.payload.append(aios.Byte("...", b"\xfe")) self.type = aios.EnumByte( "type", type.value, { ESType.uid.value: "Eddystone-UID", ESType.url.value: "Eddystone-URL", ESType.tlm.value: "Eddystone-TLM", ESType.eid.value: "Eddystone-EID", }, ) self.payload.append(self.type) self.parsed_payload = b"" self.type_payload = param
def eid_encoder(self): encodedurl = [] encodedurl.append(aios.IntByte("Tx Power", self.power)) encodedurl.append(aios.NBytes("Namespace", 8)) encodedurl[-1].val = self.type_payload self.service_data_length.val = 13 return encodedurl
def uid_encoder(self): encodedurl = [] encodedurl.append(aios.IntByte("Tx Power", self.power)) encodedurl.append(aios.NBytes("Namespace", 10)) encodedurl[-1].val = self.type_payload["namespace"] encodedurl.append(aios.NBytes("Instance", 6)) encodedurl[-1].val = self.type_payload["instance"] encodedurl.append(aios.NBytes("RFU", 2)) encodedurl[-1].val = b'\x00\x00' self.service_data_length.val = 23 #Update the payload length/ways the same for uid return encodedurl
def encode(self): # Generate the payload if self.type.val == ESType.uid.value: espayload = self.uid_encoder() elif self.type.val == ESType.url.value: espayload = self.url_encoder() elif self.type.val == ESType.tlm.value: espayload = self.tlm_encoder() elif self.type.val == ESType.eid.value: espayload = self.eid_encoder() encmsg = b"" for x in self.payload + espayload: encmsg += x.encode() mylen = aios.IntByte("Length", len(encmsg)) encmsg = mylen.encode() + encmsg for x in range(32 - len(encmsg)): encmsg += b"\x00" return encmsg
def test_decode(self): int_byte_class = aioblescan.IntByte("TestData") new_data = int_byte_class.decode(b"\x10\xf6\x03") self.assertEqual(b"\xf6\x03", new_data) self.assertEqual(16, int_byte_class.val) self.assertEqual("TestData", int_byte_class.name)
def decode(self, packet): """Check a parsed packet and figure out if it is an Eddystone Beacon. If it is , return the relevant data as a dictionary. Return None, it is not an Eddystone Beacon advertising packet""" ssu = packet.retrieve("Complete uuids") found = False for x in ssu: if EDDY_UUID in x: found = True break if not found: return None found = False adv = packet.retrieve("Advertised Data") for x in adv: luuid = x.retrieve("Service Data uuid") for uuid in luuid: if EDDY_UUID == uuid: found = x break if found: break if not found: return None try: top = found.retrieve("Adv Payload")[0] except: return None # Rebuild that part of the structure found.payload.remove(top) # Now decode result = {} data = top.val etype = aios.EnumByte( "type", self.type.val, { ESType.uid.value: "Eddystone-UID", ESType.url.value: "Eddystone-URL", ESType.tlm.value: "Eddystone-TLM", ESType.eid.value: "Eddystone-EID", }, ) data = etype.decode(data) found.payload.append(etype) if etype.val == ESType.uid.value: power = aios.IntByte("tx_power") data = power.decode(data) found.payload.append(power) result["tx_power"] = power.val nspace = aios.Itself("namespace") xx = nspace.decode( data[:10] ) # According to https://github.com/google/eddystone/tree/master/eddystone-uid data = data[10:] found.payload.append(nspace) result["name space"] = nspace.val nspace = aios.Itself("instance") xx = nspace.decode( data[:6] ) # According to https://github.com/google/eddystone/tree/master/eddystone-uid data = data[6:] found.payload.append(nspace) result["instance"] = nspace.val elif etype.val == ESType.url.value: power = aios.IntByte("tx_power") data = power.decode(data) found.payload.append(power) result["tx_power"] = power.val url = aios.EnumByte( "type", 0, { 0x00: "http://www.", 0x01: "https://www.", 0x02: "http://", 0x03: "https://", }, ) data = url.decode(data) result["url"] = url.strval for x in data: if bytes([x]) == b"\x00": result["url"] += ".com/" elif bytes([x]) == b"\x01": result["url"] += ".org/" elif bytes([x]) == b"\x02": result["url"] += ".edu/" elif bytes([x]) == b"\x03": result["url"] += ".net/" elif bytes([x]) == b"\x04": result["url"] += ".info/" elif bytes([x]) == b"\x05": result["url"] += ".biz/" elif bytes([x]) == b"\x06": result["url"] += ".gov/" elif bytes([x]) == b"\x07": result["url"] += ".com" elif bytes([x]) == b"\x08": result["url"] += ".org" elif bytes([x]) == b"\x09": result["url"] += ".edu" elif bytes([x]) == b"\x10": result["url"] += ".net" elif bytes([x]) == b"\x11": result["url"] += ".info" elif bytes([x]) == b"\x12": result["url"] += ".biz" elif bytes([x]) == b"\x13": result["url"] += ".gov" else: result["url"] += chr( x) # x.decode("ascii") #Yep ASCII only url = aios.String("url") url.decode(result["url"]) found.payload.append(url) elif etype.val == ESType.tlm.value: myinfo = aios.IntByte("version") data = myinfo.decode(data) found.payload.append(myinfo) myinfo = aios.ShortInt("battery") data = myinfo.decode(data) result["battery"] = myinfo.val found.payload.append(myinfo) myinfo = aios.Float88("temperature") data = myinfo.decode(data) found.payload.append(myinfo) result["temperature"] = myinfo.val myinfo = aios.LongInt("pdu count") data = myinfo.decode(data) found.payload.append(myinfo) result["pdu count"] = myinfo.val myinfo = aios.LongInt("uptime") data = myinfo.decode(data) found.payload.append(myinfo) result["uptime"] = myinfo.val * 100 # in msecs # elif etype.val== ESType.tlm.eid: else: result["data"] = data xx = Itself("data") xx.decode(data) found.payload.append(xx) rssi = packet.retrieve("rssi") if rssi: result["rssi"] = rssi[-1].val mac = packet.retrieve("peer") if mac: result["mac address"] = mac[-1].val return result
def test_decode(self): int_byte_class = aioblescan.IntByte('TestData') new_data = int_byte_class.decode(b'\x10\xf6\x03') self.assertEqual(b'\xf6\x03', new_data) self.assertEqual(16, int_byte_class.val) self.assertEqual('TestData', int_byte_class.name)
def RSL10v3_decode( packet, RSL10_UUID=bytes.fromhex('53ac89d1ec355ebb84e18dadb5d4db84')): """Check a parsed packet and figure out if it is a RSL10V3 Beacon. If it is , return the relevant data as a dictionary. Return None, it is not a RSL10V3 Beacon advertising packet""" found = False adv = packet.retrieve("Advertised Data") for x in adv: luuid = x.retrieve("Service Data uuid") for uuid in luuid: if RSL10_UUID == uuid: found = x break if found: break if not found: return None try: top = found.retrieve("Adv Payload")[0] except: return None #Rebuild that part of the structure found.payload.remove(top) #Now decode result = {} data = top.val print(data.hex()) # temperature myinfo = aiobs.ShortInt("temperature", endian='little') data = myinfo.decode(data) result["temperature"] = myinfo.val / 100 # humidity in percentage myinfo = aiobs.UShortInt("humidity", endian='little') data = myinfo.decode(data) result["humidity"] = myinfo.val / 100 # Pressure myinfo_lo = aiobs.UShortInt("pressure_lo", endian='little') data = myinfo_lo.decode(data) myinfo_hi = aiobs.UIntByte("pressure_hi") data = myinfo_hi.decode(data) result["pressure"] = (myinfo_lo.val + myinfo_hi.val * 65536) / 100 # format version, no need to save myinfo = aiobs.IntByte("version") data = myinfo.decode(data) # tilt_x value myinfo = aiobs.IntByte("tilt_x") data = myinfo.decode(data) result["tilt_x"] = myinfo.val # tilt_y value myinfo = aiobs.IntByte("tilt_y") data = myinfo.decode(data) result["tilt_y"] = myinfo.val # return RSSI value rssi = packet.retrieve("rssi") if rssi: result["rssi"] = rssi[-1].val mac = packet.retrieve("peer") # return MAC address if mac: result["mac address"] = mac[-1].val return result