mash-server/bettwaage-plotter/main.py

138 lines
3.5 KiB
Python
Raw Normal View History

2024-05-02 20:06:47 +02:00
import requests
import matplotlib.pyplot as plt
from datetime import datetime
2024-05-03 22:39:30 +02:00
import json
2024-05-02 20:06:47 +02:00
2024-05-03 22:39:30 +02:00
file_path = None
2024-05-02 20:06:47 +02:00
history_url = "http://192.168.178.84:9587/bettwaage/history"
2024-05-03 22:39:30 +02:00
convert_time_to_seconds = True
2024-05-02 20:06:47 +02:00
2024-05-07 16:55:12 +02:00
# Get data
2024-05-08 20:57:37 +02:00
data = None
2024-05-03 22:39:30 +02:00
if file_path is None:
2024-05-07 16:55:12 +02:00
print("Fetching data ...")
2024-05-03 22:39:30 +02:00
data = requests.get(history_url)
data = data.json()
else:
2024-05-07 16:55:12 +02:00
print("Reading data ...")
2024-05-03 22:39:30 +02:00
with open(file_path, "r") as fp:
data = json.load(fp)
2024-05-02 20:06:47 +02:00
2024-05-06 01:03:34 +02:00
2024-05-07 16:55:12 +02:00
print("Processing data ...")
# Get rough value for empty bed weight per leg
rough_bed_weight = 80
2024-05-06 01:03:34 +02:00
bed_only_weight = {}
for d in data:
2024-05-07 16:55:12 +02:00
if d["total"] < rough_bed_weight:
2024-05-06 01:03:34 +02:00
bed_only_weight = {
"tl": d["tl"],
"tr": d["tr"],
"bl": d["bl"],
2024-05-06 01:03:34 +02:00
"br": d["br"],
}
break
2024-05-07 16:55:12 +02:00
# Collect all coherent sequences of someone being in bed
in_bed_datas: list[list[dict]] = []
is_in_bed_sequence = False
threshhold = 100.0
2024-05-06 01:03:34 +02:00
for d in data:
t = d["total"]
if t >= threshhold:
2024-05-07 16:55:12 +02:00
if not is_in_bed_sequence:
in_bed_datas.append([])
is_in_bed_sequence = True
in_bed_datas[-1].append(d)
elif is_in_bed_sequence:
is_in_bed_sequence = False
# Pick latest with minimum length/duration
min_length = 100
for sequence in in_bed_datas:
if len(sequence) >= min_length:
data = sequence
# Prepare data for plotting
2024-05-03 22:39:30 +02:00
x = [d["timestamp"] for d in data]
x = [datetime.strptime(d, "%Y-%m-%d %H:%M:%S.%f") for d in x]
if convert_time_to_seconds:
max_time = max(x)
x = [(d - max_time).total_seconds() for d in x]
2024-05-02 20:06:47 +02:00
total = [d["total"] for d in data]
tl = [d["tl"] for d in data]
tr = [d["tr"] for d in data]
bl = [d["bl"] for d in data]
br = [d["br"] for d in data]
2024-05-06 01:03:34 +02:00
top = [l + r for l, r in zip(tl, tr)]
bottom = [l + r for l, r in zip(bl, br)]
left = [t + b for t, b in zip(tl, bl)]
right = [t + b for t, b in zip(tr, br)]
# Experiment: Calculate position over time
bed_size = (140, 200)
left_bed_only = bed_only_weight["tl"] + bed_only_weight["bl"]
top_bed_only = bed_only_weight["tr"] + bed_only_weight["tl"]
2024-05-07 16:55:12 +02:00
right_bed_only = bed_only_weight["tr"] + bed_only_weight["br"]
bottom_bed_only = bed_only_weight["br"] + bed_only_weight["bl"]
2024-05-06 01:03:34 +02:00
position_over_time = []
2024-05-07 16:55:12 +02:00
for t, b, l, r in zip(top, bottom, left, right):
horizontal_weight = l - left_bed_only + r - right_bed_only
vertical_weight = t - top_bed_only + b - bottom_bed_only
2024-05-06 01:03:34 +02:00
position_over_time.append(
(
2024-05-07 16:55:12 +02:00
bed_size[0] * (l - left_bed_only) / horizontal_weight,
bed_size[1] * (t - top_bed_only) / vertical_weight,
2024-05-06 01:03:34 +02:00
)
)
# Plot data
fig, (ax0, ax1) = plt.subplots(nrows=2)
ax0.set_xlabel("Time (s)")
ax0.set_ylabel("Weight (kg)")
ax0.plot(x, total, color="tab:blue")
ax0.plot(x, tl, color="tab:red")
ax0.plot(x, tr, color="tab:green")
ax0.plot(x, bl, color="tab:orange")
ax0.plot(x, br, color="tab:purple")
ax0.plot(x, top, color="tab:pink")
ax0.plot(x, bottom, color="tab:grey")
2024-05-02 20:06:47 +02:00
2024-05-06 01:03:34 +02:00
ax0.legend(
["Total", "Top Left", "Top Right", "Bottom Left", "Bottom Right", "Top", "Bottom"]
)
2024-05-02 20:06:47 +02:00
2024-05-06 01:03:34 +02:00
# Experiment: Plot position
import math
import colorsys
2024-05-02 20:06:47 +02:00
2024-05-06 01:03:34 +02:00
segments = 100
seg_length = math.ceil(len(position_over_time) / segments)
horizontal, vertical = zip(*position_over_time)
for i in range(0, segments):
low = int(i * seg_length)
high = min(int((i + 1) * seg_length), len(position_over_time))
ax1.plot(
horizontal[low:high],
vertical[low:high],
color=colorsys.hsv_to_rgb(i / segments * 0.5, 1, 0.7),
2024-05-06 01:03:34 +02:00
linewidth=0.3,
)
ax1.set_xlim((0, bed_size[0]))
ax1.set_ylim((0, bed_size[1]))
ax1.invert_yaxis()
2024-05-02 20:06:47 +02:00
plt.show()