Improve read reliability
This commit is contained in:
parent
b008f524bf
commit
f7e359af6d
1 changed files with 53 additions and 7 deletions
60
solar_ble.py
60
solar_ble.py
|
@ -230,8 +230,8 @@ def construct_request(address, words=1, action=ACTION_READ, marker=0xFF):
|
||||||
return struct.pack("!BBHH", marker, action, address, words)
|
return struct.pack("!BBHH", marker, action, address, words)
|
||||||
|
|
||||||
|
|
||||||
def log(*message: object):
|
def log(*message: object, **kwargs):
|
||||||
print(datetime.datetime.utcnow().isoformat(" "), *message)
|
print(datetime.datetime.utcnow().isoformat(" "), *message, **kwargs)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,12 +255,52 @@ def parse_packet(data):
|
||||||
return payload
|
return payload
|
||||||
|
|
||||||
|
|
||||||
def readMemory(fh: RawIOBase, address: int, words: int = 1):
|
def discardUntil(fh: RawIOBase, byte: int, timeout=10) -> Optional[int]:
|
||||||
|
assert byte >= 0 and byte < 256, f"byte: Expected 8bit unsigned int, got {byte}"
|
||||||
|
|
||||||
|
def expand(b: Optional[bytes]):
|
||||||
|
if b is None:
|
||||||
|
return b
|
||||||
|
return b[0]
|
||||||
|
|
||||||
|
start = time.time()
|
||||||
|
discarded = 0
|
||||||
|
read_byte = expand(fh.read(1))
|
||||||
|
while read_byte != byte:
|
||||||
|
|
||||||
|
if read_byte is not None:
|
||||||
|
if not discarded:
|
||||||
|
log("Discarding", end="")
|
||||||
|
discarded += 1
|
||||||
|
print(f" {read_byte:02X}", end="")
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
if time.time() - start > timeout:
|
||||||
|
read_byte = None
|
||||||
|
break
|
||||||
|
|
||||||
|
read_byte = expand(fh.read(1))
|
||||||
|
|
||||||
|
if discarded:
|
||||||
|
print()
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
return read_byte
|
||||||
|
|
||||||
|
|
||||||
|
def readMemory(fh: RawIOBase, address: int, words: int = 1) -> Optional[bytes]:
|
||||||
# log(f"Reading {words} words from 0x{address:04X}")
|
# log(f"Reading {words} words from 0x{address:04X}")
|
||||||
write(fh, construct_request(address, words=words))
|
request = construct_request(address, words=words)
|
||||||
header = fh.read(3)
|
# log("Request:", request)
|
||||||
if header and len(header) == 3:
|
write(fh, request)
|
||||||
tag, operation, size = header
|
|
||||||
|
tag = discardUntil(fh, 0xFF)
|
||||||
|
if tag is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
header = fh.read(2)
|
||||||
|
if header and len(header) == 2:
|
||||||
|
operation, size = header
|
||||||
data = fh.read(size)
|
data = fh.read(size)
|
||||||
_crc = fh.read(2)
|
_crc = fh.read(2)
|
||||||
if data and _crc:
|
if data and _crc:
|
||||||
|
@ -268,6 +308,10 @@ def readMemory(fh: RawIOBase, address: int, words: int = 1):
|
||||||
calculated_crc = modbus(bytes([tag, operation, size, *data]))
|
calculated_crc = modbus(bytes([tag, operation, size, *data]))
|
||||||
if crc == calculated_crc:
|
if crc == calculated_crc:
|
||||||
return data
|
return data
|
||||||
|
else:
|
||||||
|
log(f"readMemory: CRC error; {crc:04X} != {calculated_crc:04X}")
|
||||||
|
log("data or crc is falsely", header, data, _crc)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Periodical:
|
class Periodical:
|
||||||
|
@ -311,6 +355,8 @@ def try_read_parse(
|
||||||
log(e)
|
log(e)
|
||||||
log("0x0100 Unpack error:", len(res), res)
|
log("0x0100 Unpack error:", len(res), res)
|
||||||
log("Flushed from read buffer; ", dev.read(timeout=0.5))
|
log("Flushed from read buffer; ", dev.read(timeout=0.5))
|
||||||
|
else:
|
||||||
|
log(f"No data read, expected {words*2} bytes (attempts left: {attempts})")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue