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 __init__(self, scan_type=0x0, interval=10, window=750, oaddr_type=0, filter=0): super(self.__class__, self).__init__(b"\x08", b"\x41") self.payload.append( aiobs.EnumByte( "own addresss type", oaddr_type, { 0: "Public", 1: "Random", 2: "Private IRK or Public", 3: "Private IRK or Random" })) self.payload.append( aiobs.EnumByte( "filter policy", filter, { 0: "None", 1: "Sender In White List", 2: "Almost None", 3: "SIWL and some" })) self.payload.append( aiobs.EnumByte("primary phy", 1, { 1: "LE 1M", 3: "LE Coded" })) self.payload.append( aiobs.EnumByte("scan type", scan_type, { 0: "Passive", 1: "Active" })) self.payload.append( aiobs.UShortInt("Interval", int(round(min(10240, max(2.5, interval)) / 0.625)), endian="little")) self.payload.append( aiobs.UShortInt( "Window", int(round(min(10240, max(2.5, min(interval, window))) / 0.625)), endian="little"))
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