Created
May 17, 2025 08:02
-
-
Save kudarisenmon/76ab2a607b50e39a3fbd274ad31817c6 to your computer and use it in GitHub Desktop.
WXBeacon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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