#!/usr/bin/python # -*- coding: utf-8 -*- import matplotlib.pyplot as plt import matplotlib.dates as mdates import matplotlib.patches as mpatches from astral import LocationInfo from astral.sun import sun import datetime from json_extensions import load_from_json_file city = LocationInfo("Rome", "Italy", "Europe/Rome", 44.448066, 11.270639) def main(data): # Sample data # epoch_times = [1696000000, 1696086400, 1696172800, 1696259200] # Epoch seconds # y_values = [10, 20, 15, 25] # Some y-axis values # Create the plot fig, ax = plt.subplots(tight_layout=False, figsize=(30, 10)) earliest = None latest = None for name_raw, serie in data.items(): if name_raw in ('Security Camera', 'Ext Front'): continue name = {'Front door': 'Sample #1 No PV panel', 'Ext2': 'Sample #2 with PV Panel', }.get(name_raw, name_raw) dates = [datetime.datetime.fromtimestamp(row['epoch']) for row in serie] soc_v = [row['soc'] for row in serie] if name_raw == 'Front door': dates = dates[3:] soc_v = soc_v[3:] mi = min(dates) ma = max(dates) if earliest is None: earliest = mi latest = ma else: earliest = min(earliest, mi) latest = max(latest, ma) # charging = [row['charging'] for row in serie] # batt_full = [row['battery_full'] for row in serie] # # sizes = [] # for c1, c2 in zip(charging, batt_full): # if c1 and c2: # sizes.append(100) # Example: Both conditions true # elif c1: # sizes.append(200) # Example: Only condition 1 true # elif c2: # sizes.append(300) # Example: Only condition 2 true # else: # sizes.append(400) # Example: Both conditions false # ax.plot(dates, soc_v, '-o', lw=3, label=name) # for x, y, color in zip(dates, soc_v, sizes): # ax.plot(dates, y_values, marker='o', linestyle='-') print(earliest, latest) current_day = earliest first_time = True while current_day < latest: # print(current_day) # Get solar times s = sun(city.observer, date=current_day, tzinfo=city.timezone) dawn = s['dawn'] sunrise = s['sunrise'] sunset = s['sunset'] dusk = s['dusk'] if first_time: ax.axvspan(dawn, sunrise, color='deepskyblue', alpha=0.3, label='Twilight (-6°)') ax.axvspan(sunset, dusk, color='deepskyblue', alpha=0.3) ax.axvline(sunrise, color='orange', linestyle='--', label='Sunrise') ax.axvline(sunset, color='red', linestyle='--', label='Sunset') first_time = False else: ax.axvspan(dawn, sunrise, color='deepskyblue', alpha=0.3) ax.axvspan(sunset, dusk, color='deepskyblue', alpha=0.3) ax.axvline(sunrise, color='orange', linestyle='--') ax.axvline(sunset, color='red', linestyle='--') current_day += datetime.timedelta(days=1) # Format the x-axis as date # ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d\n%H:%M:%S')) # Customize as needed ax.xaxis.set_major_locator( mdates.AutoDateLocator(minticks=30, maxticks=60)) # Automatically adjusts for readability ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(ax.xaxis.get_major_locator())) x_tail = datetime.datetime(year=2025, month=4, day=7, hour=7, minute=20) y_tail = 85 x_head = datetime.datetime(year=2025, month=4, day=7, hour=6, minute=59) y_head = 100 dx = x_head - x_tail dy = y_head - y_tail # Rotate date labels for better visibility # plt.xticks(rotation=45) arrow = mpatches.FancyArrowPatch((x_tail, y_tail), (x_head, y_head), mutation_scale=50) ax.add_patch(arrow) # Labels and title ax.grid() ax.legend(loc='lower right', framealpha=1.0) plt.xlabel("Date & Time") plt.ylabel("Reported State of Charge [%]") plt.title('Camera battery behaviour') img_num = 1 out_name = f'{img_num}_f11.png' img_num += 1 fig.savefig(out_name, dpi=150) st1 = datetime.datetime(year=2025, month=3, day=29) end1 = datetime.datetime(year=2025, month=4, day=8, hour=12) ax.set_xlim(st1, end1) txt = f'Problems:\nSample#2: After FW upgrade the problem looks the same\nSample#1: Discharge is not monotonic.' annt = ax.text(0.3, 0.1, txt, ha='left', fontsize=20, bbox={'facecolor': 'lightgray', 'alpha': 0.85, 'pad': 5}, transform=ax.transAxes) # annt.set_text(txt) # print(txt) out_name = f'{img_num}_overview.png' # out_name_svg = f'{img_num}_overview.svg' out_name_pdf = f'{img_num}_overview.pdf' # fig.savefig(out_name_svg) fig.savefig(out_name_pdf) img_num += 1 fig.savefig(out_name, dpi=200) # # st1 = datetime.datetime(year=2025, month=3, day=1) # end1 = datetime.datetime(year=2025, month=3, day=3) # ax.set_xlim(st1, end1) # txt = f'We noticed battery level anomaly' # # print(txt) # annt = ax.text(0.1, 0.2, txt, ha='left', fontsize=20, bbox={'facecolor': 'cyan', 'alpha': 0.7, 'pad': 5}, # transform=ax.transAxes) # print(annt, type(annt)) # out_name = f'{img_num}_first_anomaly.png' # img_num += 1 # fig.savefig(out_name, dpi=150) # # annt.remove() # # st1 = datetime.datetime(year=2025, month=3, day=17) # end1 = datetime.datetime(year=2025, month=3, day=19) # ax.set_xlim(st1, end1) # txt = f'We noticed battery level anomaly Again!' # annt.set_text(txt) # # print(txt) # out_name = f'{img_num}_second_anomaly.png' # img_num += 1 # fig.savefig(out_name, dpi=150) # # st1 = datetime.datetime(year=2025, month=3, day=19) # end1 = datetime.datetime(year=2025, month=4, day=1) # ax.set_xlim(st1, end1) # txt = f'We unplugged the PV panel as asked by supplier' # annt.set_text(txt) # # print(txt) # out_name = f'{img_num}_unplugged.png' # img_num += 1 # fig.savefig(out_name, dpi=150) # # st1 = datetime.datetime(year=2025, month=3, day=29) # end1 = datetime.datetime(year=2025, month=4, day=1) # ax.set_xlim(st1, end1) # txt = f'We started testing a second sample' # annt.set_text(txt) # # print(txt) # out_name = f'{img_num}_Sample2.png' # img_num += 1 # fig.savefig(out_name, dpi=150) # # st1 = datetime.datetime(year=2025, month=3, day=30, hour=17, minute=30) # end1 = datetime.datetime(year=2025, month=3, day=31, hour=9, minute=30) # ax.set_xlim(st1, end1) # txt = f'There are Anomalies in the evening and in the morning' # annt.set_text(txt) # # print(txt) # out_name = f'{img_num}_Sample2_detail1.png' # img_num += 1 # fig.savefig(out_name, dpi=150) # # st1 = datetime.datetime(year=2025, month=3, day=31, hour=15, minute=30) # end1 = datetime.datetime(year=2025, month=4, day=1, hour=10) # ax.set_xlim(st1, end1) # txt = f'Second day Sample#2 still show anomaly\nSample#1 has increasing battery level (Impossible)' # annt.set_text(txt) # # print(txt) # out_name = f'{img_num}_Sample2_detail2.png' # img_num += 1 # fig.savefig(out_name, dpi=150) # Show the plot # plt.show() if __name__ == '__main__': cln_data = load_from_json_file('clean_data.json') main(cln_data)