import bluetooth
import time

DTU_ADDR = bytes([0x24, 0x19, 0x72, 0x61, 0x9D, 0x62])
WRITE_VH = 18
NOTIFY_VH1 = 20
NOTIFY_VH2 = 23
CCCD_VH1 = 21
CCCD_VH2 = 24

# HM-framed SET_CONFIG payload for AhoySmartHome / 106granada
PAYLOAD = bytes.fromhex('484da3100001ae6c002840017a0d41686f79536d617274486f6d6582010a3130366772616e616461')

_IRQ_PERIPHERAL_CONNECT = 7
_IRQ_PERIPHERAL_DISCONNECT = 8
_IRQ_GATTC_WRITE_DONE = 17
_IRQ_GATTC_NOTIFY = 18
_IRQ_GATTC_READ_RESULT = 15
_IRQ_MTU_EXCHANGED = 21

conn_handle = None
state = "idle"
notify_data = []
subscribed_count = [0]

ble = bluetooth.BLE()
ble.active(True)
ble.config(mtu=512)

def send_payload():
    print("Sending HM payload (%d bytes)..." % len(PAYLOAD))
    print("Payload:", PAYLOAD.hex())
    ble.gattc_write(conn_handle, WRITE_VH, PAYLOAD, 1)

def do_subscribe():
    print("Subscribing to notify chars (vh=20, vh=23)...")
    ble.gattc_write(conn_handle, CCCD_VH1, b'\x01\x00', 1)
    time.sleep_ms(400)
    ble.gattc_write(conn_handle, CCCD_VH2, b'\x01\x00', 1)
    time.sleep_ms(400)
    print("Reading write char current value...")
    ble.gattc_read(conn_handle, WRITE_VH)
    time.sleep_ms(500)
    send_payload()

def irq(event, data):
    global conn_handle, state
    if event == _IRQ_PERIPHERAL_CONNECT:
        conn_handle, _, _ = data
        print("Connected, conn=%d" % conn_handle)
        try:
            ble.gattc_exchange_mtu(conn_handle)
        except:
            do_subscribe()
    elif event == _IRQ_MTU_EXCHANGED:
        conn, mtu = data
        print("MTU exchanged: %d" % mtu)
        do_subscribe()
    elif event == _IRQ_PERIPHERAL_DISCONNECT:
        print("Disconnected")
        conn_handle = None
    elif event == _IRQ_GATTC_WRITE_DONE:
        conn, vh, status = data
        print("WRITE_DONE vh=%d status=%d" % (vh, status))
        if vh == WRITE_VH:
            state = "waiting"
            print("Payload write ACK received. Waiting for notifications...")
    elif event == _IRQ_GATTC_NOTIFY:
        conn, vh, notify_bytes = data
        nb = bytes(notify_bytes)
        print("NOTIFY vh=%d len=%d hex=%s" % (vh, len(nb), nb.hex()))
        notify_data.append((vh, nb.hex()))
    elif event == _IRQ_GATTC_READ_RESULT:
        conn, vh, char_data = data
        cd = bytes(char_data)
        print("READ vh=%d = %s ascii=%s" % (vh, cd.hex(), cd))

ble.irq(irq)

print("Connecting to DTU:", ':'.join('%02X' % b for b in DTU_ADDR))
ble.gap_connect(0, DTU_ADDR)

# Wait up to 45 seconds
for i in range(450):
    time.sleep_ms(100)
    if state == "waiting":
        pass

time.sleep(10)

print("\n=== RESULTS ===")
print("Notifications received:", len(notify_data))
for vh, hexdata in notify_data:
    print("  vh=%d: %s" % (vh, hexdata))

if conn_handle:
    print("Reading final write char value...")
    ble.gattc_read(conn_handle, WRITE_VH)
    time.sleep(2)
    ble.gap_disconnect(conn_handle)

import os
log = "Notifications: %s\nFinal read done.\n" % str(notify_data)
with open('/result.txt', 'w') as f:
    f.write(log)
print("Done.")
