Start organizing file structure

This commit is contained in:
Odd Stråbø 2023-01-04 18:05:09 +01:00
parent 0b3a38276a
commit 441e820ac4
12 changed files with 0 additions and 0 deletions

121
misc/draw_memory_map.py Normal file
View file

@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
from ast import literal_eval
from typing import Iterable, List
from solar_ble import parse_packet
from table_drawing import table
def memory_table(
data: Iterable[int],
start: int = 0,
wordsize: int = 2,
skip_nullrows: bool = True,
):
data_iter = iter(data)
data_rows: List[List[str]] = []
position = start
try:
while True:
try:
row_id = position
row = []
for _ in range(16):
try:
cell = []
for _ in range(wordsize):
d = data_iter.__next__()
cell.append(d)
finally:
if cell:
position += 1
row.append(cell)
finally:
if row:
if skip_nullrows:
is_null = not any([any(cell) for cell in row])
if is_null:
if data_rows[-1]:
data_rows.append([])
continue
row_hex = [
" ".join([f"{n:02X}" if n is not None else " " for n in cell])
for cell in row
]
row_ascii = [
" ".join(
[
" " + chr(n)
if n is not None and chr(n).isprintable()
else " "
for n in cell
]
)
for cell in row
]
row_head = f"{row_id:04X}"[:3] + "·"
data_rows.append([row_head] + row_hex)
if " ".join(row_ascii).strip():
data_rows.append([""] + row_ascii)
except StopIteration:
pass
headers = [""] + [
("" if wordsize % 2 else " ") + "···{:01X}".format(x) for x in range(16)
]
return table(
data_rows,
headers=headers,
justify="^",
# header_interval=8 * 2,
collapse_empty=True,
)
def parse_log(fh, chunksize=32):
# address = None
for line in fh.readlines():
if " " not in line:
continue
date, time, text = line.strip().split(" ", 2)
if text.startswith("Reading"):
_, addr_txt = text.split(" ")
# address = int(addr_txt.strip("."), 16)
elif text.startswith("bytearray"):
data_txt: str = text.split("(", 1)[1].strip(")")
packet = literal_eval(data_txt)
# print(address, packet)
data = parse_packet(packet)
dlen = len(data)
for i in range(chunksize):
if i < dlen:
yield data[i]
else:
yield None
with open("z_solar copy.log") as fh:
data = list(parse_log(fh))
# print(data)
# data = list(range(256))
print(
memory_table(
data,
wordsize=2,
skip_nullrows=True,
)
)
#
# rows = [[f"{x:03X}·"] for x in range(32)]
#

152
misc/memory_dump.txt Normal file
View file

@ -0,0 +1,152 @@
┌────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ │ ···0│ ···1│ ···2│ ···3│ ···4│ ···5│ ···6│ ···7│ ···8│ ···9│ ···A│ ···B│ ···C│ ···D│ ···E│ ···F│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│000·│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│18 14│14 00│20 20│20 20│4D 4C│32 34│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ M L│ 2 4│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│001·│32 30│20 20│20 20│20 20│00 04│02 00│02 00│00 03│3C 13│02 67│00 01│00 00│00 00│03 09│00 14│06 0A│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ 2 0│ │ │ │ │ │ │ │ < │ g│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│002·│00 02│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│003·│00 00│00 00│00 00│00 00│00 00│00 31│00 32│00 33│00 34│00 35│00 36│00 37│00 38│00 39│00 3A│00 3B│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ │ │ 1│ 2│ 3│ 4│ 5│ 6│ 7│ 8│ 9│ :│ ;│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│004·│00 3C│00 3D│00 3E│00 3F│00 40│00 41│00 42│00 43│00 44│00 53│00 6F│00 6C│00 61│00 72│00 20│00 43│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ <│ =│ >│ ?│ @│ A│ B│ C│ D│ S│ o│ l│ a│ r│ │ C│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│005·│00 68│00 61│00 72│00 67│00 65│00 72│00 20│00 20│00 20│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ h│ a│ r│ g│ e│ r│ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│010·│00 39│00 7B│00 00│05 05│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 7B│00 7B│00 36│00 00│00 06│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ 9│ {│ │ │ │ │ │ │ │ │ │ {│ {│ 6│ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│011·│00 00│00 02│00 00│00 19│00 00│00 04│00 00│00 00│00 00│00 05│00 00│00 00│00 00│00 3E│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ >│ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│DF0·│00 01│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│DF2·│44 44│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ D D│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│DF4·│00 00│00 00│00 00│00 00│00 00│00 00│00 00│44 44│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ │ │ │ │ D D│ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│E00·│00 00│07 D0│00 C8│FF 0C│00 02│00 A0│00 9B│00 92│00 90│00 8A│00 84│00 7E│00 78│00 6F│00 6A│64 32│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ Ð│ È│ ÿ │ │ │ │ │ │ │ │ ~│ x│ o│ j│ d 2│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│E01·│00 05│00 78│00 78│00 1E│00 03│00 41│00 A3│00 4B│00 A3│00 00│00 00│00 00│00 00│00 0F│00 05│00 05│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ x│ x│ │ │ A│ £│ K│ £│ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│E02·│00 04│01 00│00 00│00 01│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│E30·│66 66│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ f f│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│E31·│00 00│00 00│00 00│00 64│00 32│00 64│00 32│00 3C│00 05│00 C8│00 02│02 BC│00 0A│03 84│03 84│02 58│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ d│ 2│ d│ 2│ <│ │ È│ │ ¼│ │ │ │ X│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│E32·│00 14│00 60│00 00│00 00│00 00│00 00│00 00│00 00│00 01│66 66│00 00│00 00│00 00│00 00│00 00│00 00│
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ `│ │ │ │ │ │ │ │ f f│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F00·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F10·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F20·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F30·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F40·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F50·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F60·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F70·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F80·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│F90·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│FA0·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│FB0·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│FC0·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│FD0·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│FE0·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│FF0·│00 7B│00 7B│00 36│00 00│00 06│00 00│00 02│00 00│00 19│00 00│ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ {│ {│ 6│ │ │ │ │ │ │ │ │ │ │ │ │ │
├────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
└────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘

216
misc/render_rrd.py Normal file
View file

@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
import datetime
import os
from ast import literal_eval
from collections import namedtuple
from typing import Any, Dict
import rrdtool
from solar_types import DataName
DT_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
START = (
int(datetime.datetime.strptime("2021-10-31 19:28:17.502365", DT_FORMAT).timestamp())
- 1
)
# 2021-11-12 16:58:32.262030
HISTORICAL_KEYS = {
DataName.BATTERY_VOLTAGE_MIN,
DataName.BATTERY_VOLTAGE_MAX,
DataName.CHARGE_MAX_CURRENT,
DataName._DISCHARGE_MAX_CURRENT,
DataName.CHARGE_MAX_POWER,
DataName.DISCHARGE_MAX_POWER,
DataName.CHARGE_AMP_HOUR,
DataName.DISCHARGE_AMP_HOUR,
DataName.PRODUCTION_ENERGY,
DataName.CONSUMPTION_ENERGY,
DataName.RUN_DAYS,
DataName.DISCHARGE_COUNT,
DataName.FULL_CHARGE_COUNT,
DataName.TOTAL_CHARGE_AMP_HOURS,
DataName.TOTAL_DISCHARGE_AMP_HOURS,
DataName.TOTAL_PRODUCTION_ENERGY,
DataName.TOTAL_CONSUMPTION_ENERGY,
}
# 2021-11-12 16:58:47.521142
INSTANT_KEYS = {
DataName.BATTERY_CHARGE,
DataName.BATTERY_VOLTAGE,
DataName.BATTERY_CURRENT,
DataName.INTERNAL_TEMPERATURE,
DataName.BATTERY_TEMPERATURE,
DataName.LOAD_VOLTAGE,
DataName.LOAD_CURRENT,
DataName.LOAD_POWER,
DataName.PANEL_VOLTAGE,
DataName.PANEL_CURRENT,
DataName.PANEL_POWER,
DataName.LOAD_ENABLED,
}
KNOWN_KEYS = HISTORICAL_KEYS.union(INSTANT_KEYS)
MAP = {
"_internal_temperature?": "internal_temp",
"unknown1": "charge_max_current",
"unknown2": "_discharge_max_current?",
"internal_temperature": "internal_temp",
"battery_temperature": "battery_temp",
}
def map_keys(d: dict) -> dict:
res = {}
for k, v in d.items():
if k in MAP:
k = MAP[k]
res[k] = v
return res
DS = namedtuple("DS", ("name", "type", "heartbeat", "min", "max"))
def _DS2str(self: DS) -> str:
return f"DS:{self.name}:{self.type}:{self.heartbeat}:{self.min}:{self.max}"
# Mypy expects object, not DS as first argument
DS.__str__ = _DS2str # type: ignore
datapoints = [
DS("internal_temp", "GAUGE", "60s", "-70", "126"),
DS("battery_temp", "GAUGE", "60s", "-70", "126"),
DS("battery_charge", "GAUGE", "60s", "0", "100"),
DS("battery_voltage", "GAUGE", "60s", "0", "40"),
DS("battery_current", "GAUGE", "60s", "-30", "30"),
DS("load_voltage", "GAUGE", "60s", "0", "40"),
DS("load_current", "GAUGE", "60s", "-30", "30"),
DS("load_power", "GAUGE", "60s", "-800", "800"),
DS("load_enabled", "GAUGE", "60s", "0", "1"),
DS("panel_voltage", "GAUGE", "60s", "0", "120"),
DS("panel_current", "GAUGE", "60s", "-30", "30"),
DS("panel_power", "GAUGE", "60s", "-800", "800"),
]
def parse_log(fh):
# address = None
for line in fh.readlines():
if " " not in line:
continue
date, time, text = line.strip().split(" ", 2)
# print(date, time, text)
try:
dt = datetime.datetime.strptime(" ".join([date, time]), DT_FORMAT)
except ValueError as e:
print(e)
if text.startswith("{") and text.endswith("}"):
try:
data = map_keys(literal_eval(text))
except SyntaxError as e:
print(e)
for key in data.keys():
if key not in KNOWN_KEYS:
if type(key) is int:
continue
yield (dt, data)
# elif text.startswith("Reading"):
# _, addr_txt = text.split(" ")
# address = int(addr_txt.strip("."), 16)
RRDFILE = "test.rrd"
# feed updates to the database
# rrdtool.update("test.rrd", "N:32")
def rrdupdate(file: str, timestamp: int, data: dict):
res = [timestamp]
for ds in datapoints:
res.append(data.get(ds.name, "U"))
update = ":".join([str(int(x)) if type(x) is bool else str(x) for x in res])
# print(update)
rrdtool.update(file, update)
def re_read():
rrdtool.create(
RRDFILE,
# "--no-overwrite",
"--start",
str(START),
"--step=60s",
# Full resolution (1 minute) for 7 days
"RRA:MIN:0.20:1:7d",
"RRA:MAX:0.20:1:7d",
"RRA:LAST:0.20:1:7d",
"RRA:AVERAGE:0.20:1:7d",
*[str(ds) for ds in datapoints],
)
with open("z_solar.log", "r") as fh:
dt_ep_last = 0
data: Dict[str, Any] = {}
for dt, d in parse_log(fh):
# print(dt, d)
if "panel_voltage" in d or "battery_voltage" in d:
dt_ep = int(dt.timestamp())
if not dt_ep_last:
dt_ep_last = dt_ep
if dt_ep_last != dt_ep:
if not data:
continue
rrdupdate(RRDFILE, dt_ep_last, data)
data.clear()
dt_ep_last = dt_ep
# print(d)
# exit()
data.update(d)
if data:
rrdupdate(RRDFILE, dt_ep, data)
# re_read()
# DS("internal_temp", "GAUGE", "60s", "-70", "126")
# DS("battery_temp", "GAUGE", "60s", "-70", "126")
# DS("battery_charge", "GAUGE", "60s", "0", "100")
# DS("battery_voltage", "GAUGE", "60s", "0", "40")
# DS("battery_current", "GAUGE", "60s", "-30", "30")
# DS("load_voltage", "GAUGE", "60s", "0", "40")
# DS("load_current", "GAUGE", "60s", "-30", "30")
# DS("load_power", "GAUGE", "60s", "-800", "800")
# DS("load_enabled", "GAUGE", "60s", "0", "1")
# DS("panel_voltage", "GAUGE", "60s", "0", "120")
# DS("panel_current", "GAUGE", "60s", "-30", "30")
# DS("panel_power", "GAUGE", "60s", "-800", "800")
os.makedirs("graphs", exist_ok=True)
for ds in datapoints:
rrdtool.graph(
f"graphs/{ds.name}.png",
"--start=-1w",
f"--title={ds.name}",
f"DEF:{ds.name}={RRDFILE}:{ds.name}:AVERAGE",
f"LINE:{ds.name}#000000:{ds.name}",
# "LINE:panel_voltage#ff0000:Panel voltage",
# "LINE:panel_power#00ff00:Panel power",
)

116
misc/table_drawing.py Normal file
View file

@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
from typing import Collection, Optional, Union
C_UL = ""
C_UR = ""
C_LL = ""
C_LR = ""
C_V = ""
C_VL = ""
C_VR = ""
C_H = ""
C_HD = ""
C_HU = ""
C_X = ""
def row(
fields: Collection[str],
sep: str = C_V,
start: str = C_V,
end: str = C_V,
) -> str:
res = []
for i, field in enumerate(fields):
if not i:
res.append(start)
else:
res.append(sep)
res.append(field)
res.append(end)
return "".join(res)
def table(
data: Collection[Collection[str]],
headers: Optional[Collection] = None,
header_interval: Optional[int] = None,
justify: Optional[Union[str, Collection[str]]] = None,
collapse_empty: bool = False,
):
res = []
if not data:
return ""
columns = max([len(x) for x in data])
if headers:
columns = max(columns, len(headers))
if isinstance(justify, str):
justify = [justify] * columns
elif not justify:
justify = []
justify = list(justify) + ["^"] * (columns - len(justify))
colwidths = [0] * columns
if headers:
for i, col in enumerate(headers):
colwidths[i] = max(colwidths[i], len(col))
for data_row in data:
for i, col in enumerate(data_row):
colwidths[i] = max(colwidths[i], len(col))
def row_iterable():
if headers and not header_interval:
yield headers
for i, data_row in enumerate(data):
if header_interval and i % header_interval == 0:
yield headers
yield data_row
for i, data_row in enumerate(row_iterable()):
if not i:
res.append(
row([C_H * colw for colw in colwidths], start=C_UL, sep=C_HD, end=C_UR)
)
else:
res.append(
row([C_H * colw for colw in colwidths], start=C_VL, sep=C_X, end=C_VR)
)
is_empty = not any([True for x in data_row if x.strip()])
if not (is_empty and collapse_empty):
padding = [""] * (columns - len(data_row))
padded_row = [
f"{cell:{justify[j]}{colwidths[j]}s}"
for j, cell in enumerate(list(data_row) + padding)
]
res.append(row(padded_row))
res.append(row([C_H * colw for colw in colwidths], start=C_LL, sep=C_HU, end=C_LR))
return "\n".join(res)
if __name__ == "__main__":
headers = [""] + ["···{:01X}".format(x) for x in range(16)]
data = [[f"{x:03X}·"] for x in range(32)]
print(
table(
data,
headers=headers,
justify=">",
header_interval=8,
)
)

18
misc/test_bleuart.py Normal file
View file

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from feasycom_ble import BTLEUart
from solar_ble import MAC, construct_request, write
with BTLEUart(MAC, timeout=1) as x:
print(x)
write(x, construct_request(0x0E, words=3))
x.read(3, timeout=1)
print(x.read(6, timeout=0.01))
x.read(2, timeout=0.01)
print(x.timeout)
# x.timeout = 2
# print(x.read())
# print(x.read(1))