Skip to content
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

PyPortal.get_local_time() calls incorrect IP/domain #86

Open
eloekset opened this issue Jan 8, 2023 · 4 comments
Open

PyPortal.get_local_time() calls incorrect IP/domain #86

eloekset opened this issue Jan 8, 2023 · 4 comments

Comments

@eloekset
Copy link

eloekset commented Jan 8, 2023

I'm using PyPortal 7.X to create a weather station display for Netatmo. I have an on-prem ASP.NET 6 proxy against the Netatmo API, so PyPortal qeries my proxy, which queries Netatmo and prepares the response in a json structure that's easy to display as widgets on the PyPortal.

I have the following program loop:

while True:
    # only query the online time once per hour (and on first run)
    if (not localtile_refresh) or (time.monotonic() - localtile_refresh) > 3600:
        try:
            print("Getting time from internet!")
            pyportal.get_local_time()
            localtile_refresh = time.monotonic()
        except RuntimeError as e:
            print("Some error occured, retrying! -", e)
            continue

    # only query the weather every 10 minutes (and on first run)
    if (not weather_refresh) or (time.monotonic() - weather_refresh) > 600:
        try:
            value = pyportal.fetch()
            gfx.draw_display(value)
            weather_refresh = time.monotonic()
        except RuntimeError as re:
            print("Some error occured, retrying! -", re)
            gfx.draw_error()
            continue
        except TimeoutError as te:
            print("Timeout - ", te)
            gfx.draw_error()
            continue

    gfx.draw_time()
    updateTime = .5
    if mode == "weekday":
        updateTime = 30

    time.sleep(updateTime)  # wait X seconds before updating anything again

I experience unexpected behavior when pyportal.get_local_time() executes the second time (and all times after). First time the Adafruit API at http://io.adafruit.com is called as expected. But the second time, even though the URL looks correct, my local ASP.NET proxy is called instead. That's the same IP as pyportal.fetch() calls.

This is a flowchart describing what happens:
image

I added Azure Application Insights to my ASP.NET proxy to figure out what's going on, and was surprised to see requests for the domain io.adafruit.com hitting my on-prem proxy. I've documented proof of the traffic in my own project in this issue:
blog-eivindgl-com/netatmo-pyportal-display#9

I don't know why this happens, but I suspect there's some kind of local DNS issue on the PyPortal that incorrectly maps io.adafruit.com to the same IP address as the URL of the fetch() call.

@makermelissa
Copy link
Collaborator

Interesting. This will need further investigation. It doesn't look like io.adafruit.com is redirecting, so it should be hitting the same url each time.

@eloekset
Copy link
Author

I've run the PyPortal display in my own apartment for quite a while now, and the issue doesn't occur here. I guess the router in my mother's house was causing the issue.
image

@eloekset eloekset reopened this Jan 14, 2023
@eloekset
Copy link
Author

No, I'm sorry. This is not a router's fault. It happened again on my network this night. It has happened 16 times since last time PyPortal crashed, and I haven't done anything but pressing the reset button. It's hooked up a charger, so it's not connected to my computer. I don't know what's going on here, but it's obvious that suddenly traffic to http://io.adafruit.com gets routed to my service running on http://192.168.1.104. (I use a different computer to host my Docker container now, but it's still hitting that same on-prem Netatmo Proxy shown in the diagram above.)

image

I've now fixed the timezone issue on my implementation of the API, so I'm actually thinking about modifying the PyPortal source code to query my own implementation instead of http://io.adafruit.com when PyPortal.get_local_time() is executed. Since my implementation is compatible and returns the correct value now, it should just work fine:
image

The reason I'm considering that, is that PyPortal crashes quite often when refreshing the local time. Most often there's a TimeoutError:
image

Line 48 is where this function is called:
image

I don't know if it will fix the TimeoutError issue, but it's worth trying.

But this issue where traffic is suddenly hitting the wrong server should be investigated further. It could still be a router issue, but since this now has happened on two different LANs, I think it's more likely something happing on the PyPortal device - maybe in the adafruit_requests.py or the adafruit_portalbase/network.py?

@makermelissa
Copy link
Collaborator

For the timeout error, there's already an issue open in the library where the error is occurring. You can follow it here: adafruit/Adafruit_CircuitPython_ESP32SPI#170

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants