-
Notifications
You must be signed in to change notification settings - Fork 4
Fruit Jam NTP module #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
helper code to get time sync with minimal fuss on the Fruit Jam.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should use adafruit_ntp
instead of having a new npt.py
module added with this functionality. And should make use of the existing networking functionality that is already in network.py if possible.
Here is an example script based on the ntp_simpletest.py that is adapted to use the networking from this library.
import time
import rtc
from adafruit_fruitjam import FruitJam
import adafruit_connection_manager
import adafruit_ntp
fruitjam = FruitJam()
fruitjam.network.connect()
pool = adafruit_connection_manager.get_radio_socketpool(fruitjam.network._wifi.esp)
ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600)
# NOTE: This changes the system time so make sure you aren't assuming that time
# doesn't jump.
rtc.RTC().datetime = ntp.datetime
while True:
print(time.localtime())
time.sleep(1)
This code could be refactored into a function in the library for easier use.
Having it exposed as an easy to use sync_time()
function would be nice. I think that should exist on the existing Network object that is inside of network.py. So with that helper put in place user code could look like:
from adafruit_fruitjam import FruitJam
fruitjam = FruitJam()
fruitjam.network.sync_time()
# or if desired we could add a convenience accessor for it on the main FruitJam object so that this would work:
# fruitjam.sync_time()
Sounds good. I will refactor to make use of Fruit Jam network and adafruit_ntp. |
The ability to specify ntp server, tz offset and interval (same as cache_time I think?) with environment vars from settings.toml as seen in the core issue would be nice to have still too. My code doesn't account for that but it would be great to have it. |
Refactored and "works for me". I'll ask @b-blake to confirm functionality as well. • Added Network.sync_time() method in network.py • Uses adafruit_ntp + adafruit_connection_manager. • Reads optional NTP_* keys from settings.toml. • Sets rtc.RTC().datetime • Added example examples/fruitjam_time_sync.py (sync once, print localtime). • Added example examples/fruitjam_ntp_settings.toml
ntp and connection_manager libs
blank line missing.
Refactored. I've asked @b-blake to confirm functionality as well.
|
adafruit_fruitjam/network.py
Outdated
# Query NTP and set the system RTC. | ||
ntp = adafruit_ntp.NTP( | ||
pool, | ||
server=server, | ||
tz_offset=tz_offset, | ||
socket_timeout=timeout, | ||
cache_seconds=cache_seconds, | ||
) | ||
|
||
# Query NTP and set the system RTC. | ||
ntp = adafruit_ntp.NTP( | ||
pool, | ||
server=server, | ||
tz_offset=tz_offset, | ||
socket_timeout=timeout, | ||
cache_seconds=cache_seconds, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this ntp initialization need to be duplicated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also import rtc is in lines 34 and 316
Thx. I'll do a review today and check for any other duplicate behavior like those two examples |
ntp constructor removed. dup rtc import had already been removed. new NTP_RETRIES and NTP_DELAY_S user configurable settings. ``` NTP_RETRIES = 8 # number of NTP fetch attempts NTP_DELAY_S = 1.0 # delay between attempts (seconds) ``` updated settings.toml example updated docstring for sync_time with new NTP* configurables
ntp constructor removed. dup rtc import had already been removed. new NTP_RETRIES and NTP_DELAY_S user configurable settings.
updated settings.toml example updated docstring for sync_time with new NTP* configurables |
ruff was getting upset about too many branches
adafruit_fruitjam/network.py
Outdated
if last_exc and "now" not in locals(): | ||
raise last_exc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that "now" not in locals()
is getting confused here by scope or something. Or else perhaps I don't understand the intended behavior of the scope.
In any case it seems like this condition causes the current version not to work for me with default values for tuning and other arguments. In my case it seems to always time out on the first attempt, and then succeed on the second attempt. But when it gets to this check "now" not in locals()
resolves to True
which causes this to raise the OSError from the 1st attempt that timed out. Even though the second attempt succeeded.
I added this to confirm the value it resolves to and to verify that now
is definitely definied and has a date object in it.
print(f"now locals: {'now' not in locals()}")
print(now)
Here is the full output which shows these values just before the exception trace
code.py output:
Connecting to AP AloeVera
attempt: 0
caught OSError [Errno 116] ETIMEDOUT
retrying
attempt: 1
success
now locals: True
struct_time(tm_year=2025, tm_mon=8, tm_mday=25, tm_hour=21, tm_min=55, tm_sec=35, tm_wday=0, tm_yday=237, tm_isdst=-1)
Traceback (most recent call last):
File "code.py", line 114, in <module>
File "/lib/adafruit_fruitjam/__init__.py", line 266, in sync_time
File "/lib/adafruit_fruitjam/network.py", line 334, in sync_time
File "/lib/adafruit_fruitjam/network.py", line 313, in sync_time
File "adafruit_ntp.py", line 123, in datetime
File "adafruit_ntp.py", line 91, in _update_time_sync
File "/lib/adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 180, in recv_into
OSError: [Errno 116] ETIMEDOUT
I was able to resolve this locally by adding
success = False
before the attempt for
loop. And setting success = True
before the break
of a successful fetch. Then changing this condition to:
if last_exc and not success:
raise last_exc
I think that makes the intent of the condition more clear, and it seems to be working now for me with this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the latest version is changed and likely doesn't have this issue based on only a quick glance at the code. I will re-test with latest version a bit later.
examples/fruitjam_ntp_settings.toml
Outdated
@@ -0,0 +1,33 @@ | |||
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also just noticed all the copyright notices are set to my name. You can set these to your name or handle if you want.
settings.toml example with double quotes for floating point values mikeysklar attribution drop duplicate last_exc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Thanks for all of the work on this!
Tested successfully on Fruit Jam 10.0.0-beta.2
Thx @FoamyGuy for all your guidance. I think I can reduce the risk of transient TIMEOUT issues. I have some debug scripts running now. Should I start another PR for that. It will more parameter tuning than anything else. |
Mikey, Looks great to me. This was harder than it looked at the onset.. Your persistence won the day. An idea on the ETIMEOUT issue. How about time.sleep(NTP_DELAY_S( + 1))*. Bruce |
@b-blake It actually did quite well with my stress test. No failures or significantly delays.
|
I setup a twenty try loop for 30 seconds between tries. (10 minutes) Below is what I got. I had applied my patch were the delay between got larger with each ETIMEOUT. e.g. 1.5 sec, 3.0sec, 4.5 sec . . . 12 sec For reasons I cannot understand you have more reliable access to NTP and I do.. smh Bruce Init display 1.0 Hours between sync_time() attempts. 3600 Seconds. Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. Init display 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. 0.00833333 Hours between sync_time() attempts. 30 Seconds. Code done running. Press any key to enter the REPL. Use CTRL-D to reload. |
use "0.adafruit.pool.ntp.org" please |
I implemented the new NTP pool and monitored the results. Bruce |
Updating https://github.com/adafruit/Adafruit_CircuitPython_DotStar to 2.2.18 from 2.2.17: > Merge pull request adafruit/Adafruit_CircuitPython_DotStar#71 from dhalbert/spi-lock-managment Updating https://github.com/adafruit/Adafruit_CircuitPython_EPD to 2.15.0 from 2.14.0: > Merge pull request adafruit/Adafruit_CircuitPython_EPD#94 from adafruit/UC8197 > Merge pull request adafruit/Adafruit_CircuitPython_EPD#95 from adafruit/ssd1883 > Merge pull request adafruit/Adafruit_CircuitPython_EPD#93 from adafruit/ssd1680_fix > Merge pull request adafruit/Adafruit_CircuitPython_EPD#90 from AJMansfield/patch-1 Updating https://github.com/adafruit/Adafruit_CircuitPython_JD79661 to 1.0.1 from 1.0.0: > Merge pull request adafruit/Adafruit_CircuitPython_JD79661#1 from adafruit/cleanup Updating https://github.com/adafruit/Adafruit_CircuitPython_TLV320 to 1.2.1 from 1.1.0: > Merge pull request adafruit/Adafruit_CircuitPython_TLV320#11 from samblenny/fix-example-link > Merge pull request adafruit/Adafruit_CircuitPython_TLV320#10 from samblenny/volume-fixes Updating https://github.com/adafruit/Adafruit_CircuitPython_FruitJam to 1.2.0 from 0.5.0: > Merge pull request adafruit/Adafruit_CircuitPython_FruitJam#13 from FoamyGuy/volume_api > Merge pull request adafruit/Adafruit_CircuitPython_FruitJam#14 from mikeysklar/ntp-helper > Merge pull request adafruit/Adafruit_CircuitPython_FruitJam#12 from mikeysklar/headphone-speaker > Merge pull request adafruit/Adafruit_CircuitPython_FruitJam#11 from adafruit/TheKitty-patch-1 > Merge pull request adafruit/Adafruit_CircuitPython_FruitJam#9 from relic-se/request_display_config-default > Merge pull request adafruit/Adafruit_CircuitPython_FruitJam#8 from relic-se/any_button_pressed-fix Updating https://github.com/adafruit/Adafruit_CircuitPython_Bundle/circuitpython_library_list.md to NA from NA: > Added the following libraries: Adafruit_CircuitPython_UC8253
Helper module to get RTC time sync on Fruit Jam with minimal fuss. Includes example and settings.toml.
@b-blake had suggested this in the forums.
Asked for some guidance in circuitpython issue
@ladyada encouraged using the Adafruit_CircuitPython_NTP library and example code, but it was over 20 lines to get time sync and specific to the Fruit Jam.
With the NTP helper module it is two lines to set the RTC time on the Fruit Jam.