#!/usr/bin/python3 from datetime import datetime, timedelta, timezone import math import serial import sys import time TZ = timezone.utc BAUDRATE = 115200 CORRECTION = -0.012 # to compensate delay before setting the time into DS3231 SYNC_FORMAT = r"SYNC %y-%m-%d %H:%M:%S" def round_time(orig_time: datetime): new_time = orig_time + timedelta(seconds=.5) return new_time.replace(microsecond=0) def sync(arduino: serial.Serial): # Get previous state line = arduino.readline().decode('utf-8').strip() t = datetime.now(TZ) print(f"[{t}] previous state: {line}") # Wait until start of the second t = datetime.now(TZ) remain = 1.0 - math.ceil(t.microsecond) / 1_000_000 print(f"[{t}] waiting for {remain}s") time.sleep(max(remain + CORRECTION, 0)) # Do sync t = datetime.now(TZ) value = round_time(t).strftime(SYNC_FORMAT) print(f"[{t}] syncing: {value}") arduino.write(bytes(value + "\n", 'utf-8')) # Check state after sync_ok = False for i in range(6): line = arduino.readline().decode('utf-8').strip() t = datetime.now(TZ) print(f"[{t}] ARDUINO: {line}") if line == "SYNC OK": sync_ok = True if sync_ok: print("Synchronization successfully completed") else: print("ERROR: synchronization probably failed (missing SYNC OK)") if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} \n", file=sys.stderr) print("Serial device could be /dev/ttyUSB0 or similar", file=sys.stderr) sys.exit(1) try: arduino = serial.Serial(port=sys.argv[1], baudrate=BAUDRATE, timeout=3) except Exception as e: print(f"ERROR: {e}", file=sys.stderr) sys.exit(1) sync(arduino)