Yup, a problem I found which led me to my SOCKET solution. FWIW, here are the files implementing the RPI 3B+ Server and PICO clients.MicroPython itself has no understanding of time zones, doesn't have support for those in its time functions. 'localtime' is 'gmtime' and both are UTC. I have heard rumours that it will someday support time zones but don't know how that's progressing.
SERVER
Code:
# pico_rtc_server: Deliver PICO RTC datetime Tuple from another RPI__version__ = "1.0"__program__ = "pico_rtc_server.py"import syssys.path.append('/media/work/bin') # in case running in /home/pi/src#sys.path.append('/mnt/pi_lib/pico_w/common') # This is not set running in SYSTEMD#sys.path.append('/mnt/pi_lib/common')import socketimport datetime as dtimport pico_rtc_params as paramsfrom log_time import log_timefrom traceback import print_excdef get_rtc_bytes(): # https://docs.micropython.org/en/latest/library/machine.RTC.html#machine-rtc # RTC Tuple Format (year, month, day, weekday, hours, minutes, seconds, subseconds) now=dt.datetime.now() # Construct string representing the RTC tuple # Need full 8 values rtc_str=str(now.year)+","+\ str(now.month)+","+\ str(now.day)+","+\ str(now.isoweekday() )+","+\ str(now.hour)+","+\ str(now.minute)+","+\ str(now.second)+","+\ str(0) # Do not need setting lower than a second #https://www.geeksforgeeks.org/python-convert-string-to-bytes/ rtc_bytes = bytes(rtc_str, 'utf-8') return rtc_bytesdef main(): print(log_time("main")+"Program "+__program__+". Version "+__version__) # Follow log file name convention for wc_* jobs running in production if not params.debug: params.log_file=params.log_file_prefix+\ dt.datetime.now().strftime("%Y-%m-%d_%H%M%S")+".log" with open(params.log_file,"w") as f: f.write(log_time("main")+"PICO_RTC_SERVER.LOG") print(log_time("main")+"Log file = "+params.log_file) while True: try: try: s.close() # Try to close in case left open from pgm failure except: pass s = socket.socket(socket.AF_INET, \ socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET,\ socket.SO_REUSEADDR, 1) # REUSEADDR to prevent in use error# Don't want to on server side s.settimeout(params.timeout) # In case of already in use see https://bobbyhadz.com/blog/socket-error-errno-98-address-already-in-use-in-python # $ lsof -i :{port) # $ sudo kill -9 {pid} s.bind((params.host, params.port)) s.listen() while True:# Keep Accepting Calls conn, addr = s.accept() with conn: with open(params.log_file,"a") as f: f.write(log_time("main")+f"Connected by {addr}") if params.debug: print(log_time("main")+f"Connected by {addr}") data = conn.recv(1024) # Dummy payload to trigger send msg=f".... Data {data}" with open(params.log_file,"a") as f: f.write(log_time("main")+msg) if params.debug: print(log_time("main")+msg) # This loop work in simple testing. Don't know why the recv hangs here # while True:# data = conn.recv(1024) # Dummy payload to trigger send# if params.debug: print(log_time("main")+f"Data {data}") # if not data:# break# # End of .recv loop rtc_bytes=get_rtc_bytes() # Get RTC tuple in bytes msg=f".... Returning {rtc_bytes}" with open(params.log_file,"a") as f: f.write(log_time("main")+msg) if params.debug: print(log_time("main")+msg) conn.sendall(rtc_bytes) # end of conn with # End of .accept loop # This except catches all errors and will restart the socket process except KeyboardInterrupt: print("CNTL-C") return except Exception as err: with open(params.log_file,"a") as f: f.write(log_time("main")+"Exception caught\n") print_exc(file=f) if params.debug: print(log_time("main")+"Exception "+str(err)) return # End of main loop#************************************************************************************************if __name__ == '__main__': main()Code:
#pico_rtc_server.py Parameters# Common parmsdebug=Falseif debug: work_dir="."else: work_dir="/media/work"log_file=work_dir+"/log/pico_rtc_server.log"log_file_prefix=work_dir+"/log/pico_rtc_server_"# Socket parms#host="" # Use empty string so all IP addresses used.host="wethCAM.local"port=65432timeout=5Code:
# set_rtc(): Set the Real Time Clock on the PICO W# V2 2024-01-26 - Notified that timezone API is no longer free.# Switching to SOCKET program call to wethCAM.local to get# date and time. See set_rtc.py for previous descriptions.# This function is called by both BOOT.PY and MAIN.PY since the RTC needs to be# updated every few hour.# The PICO W has a RTC but not supported by a battery. That means that# when the PICO loses power, so does the RTC. It will boot up with its# 'epoch' of 2021-01-01 00:00:00.# Getting the correct time in Micropyton is also complicated because# MP does not support time zones.# This V2 function uses a SOCKET call to wethCAM.local to retrieve date/time# Set PICO RTC# https://docs.micropython.org/en/latest/library/machine.RTC.html#class-rtc-real-time-clock# https://mpython.readthedocs.io/en/master/library/micropython/machine/machine.RTC.html# ... it is recommended to perform time calibration every 7 hours.# https://github.com/micropython/micropython/issues/10578# ports/rtc: Inconsistencies between ports and the documentationfrom machine import RTCfrom sys import print_exception# https://docs.micropython.org/en/latest/library/socket.htmlimport socketfrom log_time import log_timeimport rtc_params as paramsdef set_rtc(log_file): # log_file is the name to write log entries to service_used="pico_rtc_server" try: sockaddr = socket.getaddrinfo(params.host, params.port)[0][-1] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.settimeout(params.timeout) s.connect(sockaddr) s.sendall(bytes(log_file, 'utf-8'))# Dummy payload as byte type rtc_byte= s.recv(1024) # Get RTC payload from wethCAM.local rtc_str = str(rtc_byte, 'UTF-8') # Convert byte to str tup = tuple(map(int, rtc_str.split(','))) # Convert str to tuple rtc=RTC() rtc.datetime(tup) s.close() except Exception as err: with open(log_file,"a") as f: f.write(log_time("set_rtc()")+"Exception caught") print_exception(err,f) return False, service_used return True, service_usedCode:
host="wethCAM.local" # wethcam.LOCALport=65432timeout=60 # secondsStatistics: Posted by DS256 — Sat Apr 05, 2025 2:01 pm