diff --git a/solar_ble.py b/solar_ble.py index bfded7c..2ab47b7 100755 --- a/solar_ble.py +++ b/solar_ble.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- import datetime import struct +import sys import time from bluepy import btle @@ -200,6 +201,7 @@ def parsePacket(data): print(timestamp, res) return res print(timestamp, data) + sys.stdout.flush() class Delegate(btle.DefaultDelegate): @@ -227,36 +229,80 @@ def write(fh, data): fh.write(data + bcrc) -dlgt = Delegate() - -prev = time.time() - INTERVAL +def construct_request(address, words=1): + return struct.pack("!BBHH", 0xFF, 0x03, address, words) -while True: - try: - with btle.Peripheral(MAC).withDelegate(dlgt) as dev: +def poll(dev: btle.Peripheral, timeout: float = 1) -> bool: + start = time.time() + while not dev.waitForNotifications(0.2): + if time.time() < start + timeout: + return False - wd = dev.getCharacteristics(uuid=write_device)[0] + while dev.waitForNotifications(0.2): + pass - while True: - dev.waitForNotifications(1) + return True - now = time.time() - diff = now - prev - if diff >= INTERVAL: - prev += INTERVAL - write(wd, CMD_GET_PANEL_STATUS) - dev.waitForNotifications(1) +def log(string: str): + print(datetime.datetime.utcnow().isoformat(" "), string) + sys.stdout.flush() - write(wd, CMD_GET_BATTERY_STATE) - dev.waitForNotifications(1) - # if STATUS.get('load_enabled'): - # write(wd, CMD_DISABLE_LOAD) - # else: - # write(wd, CMD_ENABLE_LOAD) +if __name__ == "__main__": + dlgt = Delegate() - except btle.BTLEDisconnectError: - print(datetime.datetime.utcnow().isoformat(" "), "ERROR: Disconnected") - time.sleep(1) + prev = time.time() - INTERVAL + + while True: + try: + log("Connecting...") + with btle.Peripheral(MAC).withDelegate(dlgt) as dev: + wd = dev.getCharacteristics(uuid=write_device)[0] + + log("Connected.") + + poll(dev) + + write(wd, construct_request(0, 32)) + poll(dev) + poll(dev) + poll(dev) + + # Memory dump + # for address in range(0, 0x10000, 16): + # log(f"Reading 0x{address:04X}...") + # write(wd, construct_request(address, 16)) + # poll(dev) + # poll(dev) + # poll(dev) + # poll(dev) + # poll(dev) + + while True: + poll(dev) + + now = time.time() + diff = now - prev + if diff >= INTERVAL: + prev += INTERVAL + + write(wd, construct_request(0x0107, 4)) # CMD_GET_PANEL_STATUS + poll(dev) + + write(wd, construct_request(0x0100, 7)) # CMD_GET_BATTERY_STATE + poll(dev) + + # if STATUS.get('load_enabled'): + # write(wd, CMD_DISABLE_LOAD) + # else: + # write(wd, CMD_ENABLE_LOAD) + + except btle.BTLEDisconnectError: + log("ERROR: Disconnected") + time.sleep(1) + try: + dev.close() + except Exception: + pass