From b493d30a419814dd3e20cec583b529f5ebfe3434 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 5 Mar 2025 16:07:22 +0100 Subject: [PATCH] update --- RTC/set_with_NTP.py | 158 +++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 39 deletions(-) diff --git a/RTC/set_with_NTP.py b/RTC/set_with_NTP.py index 33b3c5b..51fd756 100755 --- a/RTC/set_with_NTP.py +++ b/RTC/set_with_NTP.py @@ -1,11 +1,9 @@ +#!/usr/bin/python3 """ Script to set the RTC using an NTP server. RPI needs to be connected to the internet (WIFI). Requires ntplib and pytz: sudo pip3 install ntplib pytz --break-system-packages - -/usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/set_with_NTP.py - """ import smbus2 import time @@ -49,49 +47,131 @@ def set_time(bus, year, month, day, hour, minute, second): ]) def read_time(bus): - """Read the RTC time.""" - data = bus.read_i2c_block_data(DS3231_ADDR, REG_TIME, 7) - second = bcd_to_dec(data[0] & 0x7F) - minute = bcd_to_dec(data[1]) - hour = bcd_to_dec(data[2] & 0x3F) - day = bcd_to_dec(data[4]) - month = bcd_to_dec(data[5]) - year = bcd_to_dec(data[6]) + 2000 - return (year, month, day, hour, minute, second) + """Read the RTC time and validate the values.""" + try: + data = bus.read_i2c_block_data(DS3231_ADDR, REG_TIME, 7) + + # Convert from BCD + second = bcd_to_dec(data[0] & 0x7F) + minute = bcd_to_dec(data[1]) + hour = bcd_to_dec(data[2] & 0x3F) + day = bcd_to_dec(data[4]) + month = bcd_to_dec(data[5]) + year = bcd_to_dec(data[6]) + 2000 + + # Print raw values for debugging + print(f"Raw RTC values: {data}") + print(f"Decoded values: Y:{year} M:{month} D:{day} H:{hour} M:{minute} S:{second}") + + # Validate date values + if not (1 <= month <= 12): + print(f"Invalid month value: {month}, using default") + month = 1 + + # Check days in month (simplified) + days_in_month = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + if not (1 <= day <= days_in_month[month]): + print(f"Invalid day value: {day} for month {month}, using default") + day = 1 + + # Validate time values + if not (0 <= hour <= 23): + print(f"Invalid hour value: {hour}, using default") + hour = 0 + + if not (0 <= minute <= 59): + print(f"Invalid minute value: {minute}, using default") + minute = 0 + + if not (0 <= second <= 59): + print(f"Invalid second value: {second}, using default") + second = 0 + + return (year, month, day, hour, minute, second) + + except Exception as e: + print(f"Error reading RTC: {e}") + # Return a safe default date (2023-01-01 00:00:00) + return (2023, 1, 1, 0, 0, 0) def get_internet_time(): """Get the current time from an NTP server.""" ntp_client = ntplib.NTPClient() - response = ntp_client.request('pool.ntp.org') - utc_time = datetime.utcfromtimestamp(response.tx_time) - return utc_time + # Try multiple NTP servers in case one fails + servers = ['pool.ntp.org', 'time.google.com', 'time.windows.com', 'time.apple.com'] + + for server in servers: + try: + print(f"Trying NTP server: {server}") + response = ntp_client.request(server, timeout=2) + utc_time = datetime.utcfromtimestamp(response.tx_time) + print(f"Successfully got time from {server}") + return utc_time + except Exception as e: + print(f"Failed to get time from {server}: {e}") + + # If all servers fail, raise exception + raise Exception("All NTP servers failed") def main(): - bus = smbus2.SMBus(1) - - # Get the current time from the RTC - year, month, day, hours, minutes, seconds = read_time(bus) - rtc_time = datetime(year, month, day, hours, minutes, seconds) - - # Get current UTC time from an NTP server try: - internet_utc_time = get_internet_time() - print(f"Time from Internet (UTC) : {internet_utc_time.strftime('%Y-%m-%d %H:%M:%S')}") + bus = smbus2.SMBus(1) + + # Test if RTC is accessible + try: + bus.read_byte(DS3231_ADDR) + print("RTC module is accessible") + except Exception as e: + print(f"Error accessing RTC module: {e}") + print("Please check connections and I2C configuration") + return + + # Get the current time from the RTC + try: + year, month, day, hours, minutes, seconds = read_time(bus) + # Create datetime object with validation to handle invalid dates + rtc_time = datetime(year, month, day, hours, minutes, seconds) + print(f"Actual RTC Time : {rtc_time.strftime('%Y-%m-%d %H:%M:%S')}") + except ValueError as e: + print(f"Invalid date/time read from RTC: {e}") + print("Will proceed with setting RTC from internet time") + rtc_time = None + + # Get current UTC time from an NTP server + try: + internet_utc_time = get_internet_time() + print(f"Time from Internet (UTC) : {internet_utc_time.strftime('%Y-%m-%d %H:%M:%S')}") + except Exception as e: + print(f"Error retrieving time from the internet: {e}") + if rtc_time is None: + print("Cannot proceed without either valid RTC time or internet time") + return + print("Will keep current RTC time") + return + + # Set the RTC to UTC time + print("Setting RTC to internet time...") + set_time(bus, internet_utc_time.year, internet_utc_time.month, internet_utc_time.day, + internet_utc_time.hour, internet_utc_time.minute, internet_utc_time.second) + + # Read and print the new time from RTC + print("Reading back new RTC time...") + year, month, day, hour, minute, second = read_time(bus) + rtc_time_new = datetime(year, month, day, hour, minute, second) + print(f"New RTC Time (UTC) : {rtc_time_new.strftime('%Y-%m-%d %H:%M:%S')}") + + # Calculate difference to verify accuracy + time_diff = abs((rtc_time_new - internet_utc_time).total_seconds()) + print(f"Time difference : {time_diff:.2f} seconds") + + if time_diff > 5: + print("Warning: RTC time differs significantly from internet time") + print("You may need to retry or check RTC module") + else: + print("RTC successfully synchronized with internet time") + except Exception as e: - print(f"Error retrieving time from the internet: {e}") - return - - # Print current RTC time - print(f"Actual RTC Time : {rtc_time.strftime('%Y-%m-%d %H:%M:%S')}") - - # Set the RTC to UTC time - set_time(bus, internet_utc_time.year, internet_utc_time.month, internet_utc_time.day, - internet_utc_time.hour, internet_utc_time.minute, internet_utc_time.second) - - # Read and print the new time from RTC - year, month, day, hour, minute, second = read_time(bus) - rtc_time_new = datetime(year, month, day, hour, minute, second) - print(f"New RTC Time (UTC) : {rtc_time_new.strftime('%Y-%m-%d %H:%M:%S')}") + print(f"Unexpected error: {e}") if __name__ == "__main__": - main() + main() \ No newline at end of file