#!/home/ajv/work/venv313/python

# cPy - USB time server
# Copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2026-07-14  initial release

import  subprocess;         subprocess.run('clear')
import	time, json
import	datetime			as	dt
import	serial				# (venv) pip install pyserial

# on receiving 'time': send [year, month, day, hour, minute, second, n, n]
#    as required by Esp32 RTC.init()

# Windows: see uart_cross.png
# linux  : $ socat -d -d pty,rawer,echo=0 pty,rawer,echo=0
#            --> /dev/pts/1 and /dev/pts/2
#		   $ picocom -q /dev/pts/2

# Implemented:
# Serial(port)
#    Serial.writeLn(obj)
#    Serial.readLn()            -->  obj | None

# ============================= Serial =============================

# Class for obj serial UART / USB communication
class Serial:
    
    def __init__(self, port):
        self.comm = None
        self.comm = serial.Serial(port, baudrate=115200, timeout=0)
        self.rx_buff = b''
        
        
    # write <CR><LF> terminated obj as bytes
    def writeLn(self, obj):
        try:
            if not isinstance(obj, str):
                obj = json.dumps(obj)                        
            self.comm.write(f'{obj}\r\n'.encode())
        except: print('Serial.writeLn: exception')
        
        
    # return received <CR> or <LF> terminated obj or None. Non blocking
    def readLn(self):
        while ch := self.comm.read(1):
            if ch in b'\n\r':
                if self.rx_buff:
                    obj, self.rx_buff = self.rx_buff.decode(), b''
                    try:    obj = json.loads(obj)
                    except: pass
                    return obj
            else: self.rx_buff += ch
        
# ======================== test UART communication ============================

# send time as list after receiving 'time'
# year, month, day, hours, minutes, seconds, weekday, yearday, utc_offs
def timeServer(port):
    print('Time server running ...')
    try:
        comm = Serial(port)						# open serial port
        while True:
            if s_rx := comm.readLn():			# if a line received
                if s_rx == 'time':
                    x = dt.datetime.now()
                    x = dt.datetime.timetuple(x)
                    comm.writeLn(x)				# send datetime as list
                    print('Tx:', list(x))
            time.sleep(0.1)
    except serial.serialutil.SerialException:
        print('Exception, unable to connect to:', port)
        

timeServer('/dev/ttyUSB1')				# Thonny ESP32 on /dev/ttyUSB0
# timeServer('/dev/pts/2')		

# ================================== end =====================================
