Skip to content

Instantly share code, notes, and snippets.

@kudarisenmon
Created May 17, 2025 08:02
Show Gist options
  • Select an option

  • Save kudarisenmon/76ab2a607b50e39a3fbd274ad31817c6 to your computer and use it in GitHub Desktop.

Select an option

Save kudarisenmon/76ab2a607b50e39a3fbd274ad31817c6 to your computer and use it in GitHub Desktop.
WXBeacon
import asyncio
from bleak import BleakScanner
ibeacon_found_event = asyncio.Event() # フラグとして使用
def parse_ibeacon(manufacturer_data: bytes):
# AppleのiBeaconフォーマットか簡易チェック
if len(manufacturer_data) < 23:
return None
if manufacturer_data[0] != 0x02 or manufacturer_data[1] != 0x15:
# iBeaconタイプと長さでない場合は処理しない
return None
uuid = manufacturer_data[2:18]
major = int.from_bytes(manufacturer_data[18:20], byteorder='big')
minor = int.from_bytes(manufacturer_data[20:22], byteorder='big')
tx_power = int.from_bytes(manufacturer_data[22:23], byteorder='big', signed=True)
uuid_str = '-'.join([
uuid[0:4].hex(),
uuid[4:6].hex(),
uuid[6:8].hex(),
uuid[8:10].hex(),
uuid[10:16].hex()
])
return {
"uuid": uuid_str,
"major": major,
"minor": minor,
"tx_power": tx_power
}
def detection_callback(device, advertisement_data):
adv = advertisement_data.manufacturer_data
if not adv:
return
for company_id, data in adv.items():
if company_id != 0x004C: # Apple
continue
ibeacon = parse_ibeacon(data)
if not ibeacon or ibeacon['uuid'] != 'c722db4c-5d91-1801-beb5-001c4de7b3fd' :
continue
print(f"Device: {device.address} (Apple iBeacon)")
print(f" UUID: {ibeacon['uuid']}")
print(f" Major: {ibeacon['major']}")
print(f" Minor: {ibeacon['minor']}")
print(f" TxPower: {ibeacon['tx_power']} dBm")
print(f" Raw Data: {data.hex()}\n")
temperature = (((ibeacon['major'] >> 4) & 0x03FF) * 100 - 30000) / 1000.0
humidity = ((ibeacon['major'] << 3) & 0x0078) | ((ibeacon['minor'] >> 13) & 0x0007)
pressure = round(((ibeacon['minor'] & 0x1FFF) * 0.1 + 300), 1)
print(f" 温度: {temperature} °C")
print(f" 湿度: {humidity} %")
print(f" 気圧: {pressure} hPa\n")
ibeacon_found_event.set() # iBeacon が見つかったらフラグを立てる
async def scan_ble_until_found_or_timeout():
scanner = BleakScanner(detection_callback=detection_callback)
await scanner.start()
print("Scanning for up to 30 seconds or until iBeacon is found...")
try:
# どちらか早い方が来たら停止
await asyncio.wait_for(ibeacon_found_event.wait(), timeout=30.0)
print("iBeacon found. Stopping scan.")
except asyncio.TimeoutError:
print("Timeout reached. No iBeacon found.")
finally:
await scanner.stop()
if __name__ == "__main__":
asyncio.run(scan_ble_until_found_or_timeout())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment