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

Star_Fragment_Lamp code has an issue with sunrise #2609

Open
clarkiej opened this issue Aug 30, 2023 · 11 comments
Open

Star_Fragment_Lamp code has an issue with sunrise #2609

clarkiej opened this issue Aug 30, 2023 · 11 comments
Assignees

Comments

@clarkiej
Copy link

clarkiej commented Aug 30, 2023

Board flashed with adafruit-circuitpython-adafruit_qtpy_esp32s2-en_GB-8.2.4.uf2
Used CircuitPython 8.x code / library version

The lamp has no issues with determining sunset and approx.one hour outy and slowly increasing brightness till sunset is reached:

17:13:32.913 -> pinging Open-Meteo
17:13:40.931 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=17, tm_min=13, tm_sec=40, tm_wday=2, tm_yday=241, tm_isdst=0)
17:13:40.976 -> 0 hour(s) until sunset
17:13:40.976 -> 48 minutes(s) until sunset
17:13:40.976 -> 2023-08-29T18:02
17:13:40.976 -> 0
17:13:40.976 ->
17:13:40.976 -> pinging Open-Meteo
17:13:48.915 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=17, tm_min=13, tm_sec=47, tm_wday=2, tm_yday=241, tm_isdst=0)
17:13:48.959 -> 0 hour(s) until sunset
17:13:48.959 -> 48 minutes(s) until sunset <<--approx one hour hout it goes into teh countown loop increasing LED brightness
17:13:48.959 -> 2023-08-29T18:02
17:13:48.959 -> 47.5424
17:13:48.959 ->

Once sunset time is reached "the star is glowing" waits till after midnight to look for sunrise:

18:00:03.974 -> pinging Open-Meteo
18:00:11.164 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=18, tm_min=0, tm_sec=10, tm_wday=2, tm_yday=241, tm_isdst=0)
18:00:11.164 -> 0 hour(s) until sunset
18:00:11.164 -> 1 minutes(s) until sunset
18:00:11.164 -> 2023-08-29T18:02
18:00:11.164 -> 229.068
18:00:11.164 ->
18:05:04.015 -> pinging Open-Meteo
18:05:11.282 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=18, tm_min=5, tm_sec=10, tm_wday=2, tm_yday=241, tm_isdst=0)
18:05:11.315 -> 23 hour(s) until sunset
18:05:11.315 -> 56 minutes(s) until sunset
18:05:11.315 -> 2023-08-29T18:02
18:05:11.315 -> 250.678
18:05:11.315 ->
18:05:11.315 -> star is glowing
18:30:06.932 -> not looking for sunrise
18:30:06.979 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=18, tm_min=30, tm_sec=6, tm_wday=2, tm_yday=241, tm_isdst=0)
18:30:06.979 ->

The trouble is that approx. 1 hour out from sunrise, instead of counting down to sunrise and decreasing brightness, the star is instead turned off and the lamp goes back to looking for sunset:

05:26:57.051 ->
05:41:49.895 -> pinging Open-Meteo
05:41:57.433 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=5, tm_min=41, tm_sec=57, tm_wday=2, tm_yday=241, tm_isdst=0)
05:41:57.479 -> 0 hour(s) until sunrise
05:41:57.479 -> 59 minutes(s) until sunrise
05:41:57.479 -> 2023-08-29T06:40
05:41:57.479 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=5, tm_min=41, tm_sec=57, tm_wday=2, tm_yday=241, tm_isdst=0)
05:41:57.479 -> 05:41:57.479 -> 0 hour(s) until sunrise
05:41:57.479 -> 59 minutes(s) until sunrise
05:41:57.479 -> 2023-08-29T06:40
05:41:57.479 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=5, tm_min=41, tm_sec=57, tm_wday=2, tm_yday=241, tm_isdst=0)
05:41:57.479 ->
05:41:57.479 -> star is off <<-- one hour out instead of counting down the lamp is turned off
05:56:49.925 -> pinging Open-Meteo
05:56:57.751 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=29, tm_hour=5, tm_min=56, tm_sec=56, tm_wday=2, tm_yday=241, tm_isdst=0)
05:56:57.751 -> 12 hour(s) until sunset
05:56:57.751 -> 4 minutes(s) until sunset
05:56:57.751 -> 2023-08-29T18:02
05:56:57.751 -> 0

@BlitzCityDIY
Copy link
Collaborator

hihi- thanks for the serial output. in looking at the code, i'm wondering if it's the rise_time and set_time variables not being reset. can you try adding rise_time = divide_time(sunrise) to looking_for_sunrise (line 229):

if looking_for_sunrise:
                    print("pinging Open-Meteo")
                    sunrise, sunset = sun_clock()
                    rise_time = divide_time(sunrise)
                    (total_until_rise, hours_until_sunrise,
                    mins_until_sunrise, now) = sun_countdown(rise_time)

and set_time = divide_time(sunset) to the sunset portion (line 188):

if first_run or ticks_diff(ticks_ms(), clock) > time_check:
                print("pinging Open-Meteo")
                sunrise, sunset = sun_clock()
                set_time = divide_time(sunset)
                (total_until_set, hours_until_sunset,
                mins_until_sunset, now) = sun_countdown(set_time)

@clarkiej
Copy link
Author

clarkiej commented Aug 30, 2023

Thank you for your prompt reply. Much appreciated. I had someone help me in working out how access the serial output, and adding the time stamp to see what is actually happening when relative to my time. I have made the change and let you know the result.

@clarkiej
Copy link
Author

clarkiej commented Aug 30, 2023

I also have a second problem with my location and timezone.

If I enter my Lat/Long as Perth

lat = -31.95224
long = 115.8614

and even type my location as Australia/Perth

location = "Australia/Perth"

and power up teh lamp, the correct sunrise and sunset times are pulled from the API, but the star glow is set to false and the lamp is off, even though sunrise has not yet occured :

Location set to Perth with timestamp showing Perth Time (2023-08-31)

04:31:33.325 -> �]0;🐍192.168.1.241 | code.py | 8.2.4�\struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=31, tm_sec=36, tm_wday=4, tm_yday=243, tm_isdst=0)
04:31:40.832 -> 2023-08-31T06:37 <<-- Perth Sunrise
04:31:40.878 -> 2023-08-31T18:03 <<-- Perth Sunset
04:31:44.682 -> 48676
04:31:44.682 -> star glow false <<-- sunrise still ahead but lamp off
04:31:44.682 -> pinging Open-Meteo
04:31:51.633 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=31, tm_sec=51, tm_wday=4, tm_yday=243, tm_isdst=0)
04:31:51.633 -> 13 hour(s) until sunset
04:31:51.633 -> 31 minutes(s) until sunset
04:31:51.633 -> 2023-08-31T18:03
04:31:51.633 -> 0

Same applies if I set my LAT/LONG and Location to "Asia/Singapore"

This means if there is a connection loss and a soft reset after midnight, then the lamp will turn off and track time to sunset.

But if I set my LAT/LONG to London and location to "UK/London" then it sees that the sun has not risen, lamp is turned on and time to sunrise is tracked

Time Stamp still Perth time (2023-08-31)
04:50:11.769 -> code.py output:
04:50:11.769 -> �]0;🐍192.168.1.241 | code.py | 8.2.4�\struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=50, tm_sec=15, tm_wday=4, tm_yday=243, tm_isdst=0)
04:50:19.379 -> 2023-08-30T06:10 <<-- London Sunrise
04:50:19.380 -> 2023-08-30T19:51 <<-- London Sunset
04:50:23.212 -> -32363
04:50:23.212 -> star glow true <<-- Sunrise still ahead turn on lamp
04:50:23.212 -> pinging Open-Meteo
04:50:30.175 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=50, tm_sec=29, tm_wday=4, tm_yday=243, tm_isdst=0)
04:50:30.208 -> 1 hour(s) until sunrise
04:50:30.208 -> 19 minutes(s) until sunrise
04:50:30.208 -> 2023-08-30T06:10
04:50:30.208 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=50, tm_sec=29, tm_wday=4, tm_yday=243, tm_isdst=0)
04:50:30.208 ->

@BlitzCityDIY
Copy link
Collaborator

ah okay i think this has to do with the first_run parameter. it assumes it's during daylight hours (looking for sunset). i'm going to add some logic so that it determines before the loop dynamically if it's night or day.

@clarkiej
Copy link
Author

clarkiej commented Aug 30, 2023

Update:
This is the result of teh code change. I was able to have the lamp glow when powering up after midnight and before sunrise for testing by using London as my LAT/Long and it has just hit one hour before sunrise, but it is still ignoring the loop countdown and turning the lamp off:

04:55:36.985 -> �]0;🐍Wi-Fi: No IP | Done | 8.2.4�
04:55:39.149 -> Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
04:55:39.149 -> code.py output:
04:55:39.149 -> �]0;🐍192.168.1.241 | code.py | 8.2.4�\struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=55, tm_sec=42, tm_wday=4, tm_yday=243, tm_isdst=0)
04:55:46.645 -> 2023-08-30T06:10 <<--London Sunrise as it is showing yesterday's (for me) date
04:55:46.645 -> 2023-08-30T19:51
04:55:50.486 -> -32690
04:55:50.486 -> star glow true
04:55:50.486 -> pinging Open-Meteo
04:55:57.419 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=55, tm_sec=57, tm_wday=4, tm_yday=243, tm_isdst=0)
04:55:57.465 -> 1 hour(s) until sunrise
04:55:57.465 -> 14 minutes(s) until sunrise
04:55:57.465 -> 2023-08-30T06:10
04:55:57.465 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=4, tm_min=55, tm_sec=57, tm_wday=4, tm_yday=243, tm_isdst=0)
04:55:57.465 ->
05:10:50.478 -> pinging Open-Meteo
05:10:57.618 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=5, tm_min=10, tm_sec=57, tm_wday=4, tm_yday=243, tm_isdst=0)
05:10:57.664 -> 0 hour(s) until sunrise
05:10:57.664 -> 59 minutes(s) until sunrise <<-- less than an hour to go to sunup
05:10:57.664 -> 2023-08-30T06:10
05:10:57.664 -> struct_time(tm_year=2023, tm_mon=8, tm_mday=31, tm_hour=5, tm_min=10, tm_sec=57, tm_wday=4, tm_yday=243, tm_isdst=0)
05:10:57.664 ->
05:10:57.664 -> star is off <<-- oops

@clarkiej
Copy link
Author

Have you been able to investigate this any further?

@that-fleps
Copy link

I've been working through debugging my Star-Fragment lamp too and it seems like I've come across something that could at least be related or maybe a confounding issue, so I'll add some notes here in case it helps.

Brief summary of findings so far: there was some discussion on the Adafruit Forum of a Star-Fragment lamp not working at https://forums.adafruit.com/viewtopic.php?t=204011 and my lamp - which also used to work ok - seemed to have stopped tracking sunset times (it was used mostly as a nightlight before bedtime). If switched on in the evening:

  • before sunset (I expected it to brighten within the last hour before sunset) it didn't brighten/switch on
  • after sunset (I expected it to switch on full brightness straight away) it didn't switch on

This change seemed to have happened sometime around the end of August 2023. I'm not sure exactly when as we were away travelling and the lamp wasn't being used.

In attempting to work out why it wasn't behaving, I checked the log output in the REPL pane of the Mu editor, which (at just after 7pm on 10th September in New Zealand) looked something like:

code.py output:
struct_time(tm_year=2023, tm_mon=9, tm_mday=10, tm_hour=7, tm_min=8, tm_sec=30, tm_wday=0, tm_yday=253, tm_isdst=0)

2023-09-10T06:34
2023-09-10T18:07
39503
star glow false
pinging Open-Meteo
struct_time(tm_year=2023, tm_mon=9, tm_mday=10, tm_hour=7, tm_min=8, tm_sec=44, tm_wday=0, tm_yday=253, tm_isdst=0)

10 hour(s) until sunset
58 minutes(s) until sunset
2023-09-10T18:07
0

which looked mostly ok, except the time in the struct_time returned by the IO_HTTP call to AdafruitIO appears to be 12 hours before my local time (Pacific/Auckland). From there the time-to-sunset calculation looks like it's performed correctly, just based on the wrong current time.

My understanding is that the IO_HTTP call doesn't take a timezone/location parameter and instead determines the client's timezone by IP address. So in Auckland I would have expected the struct_time to look like

struct_time(tm_year=2023, tm_mon=9, tm_mday=10, tm_hour=**19**, tm_min=8, tm_sec=44, tm_wday=0, tm_yday=253, tm_isdst=0)

As a follow-up I tried using an alternative method for getting local time, based on an example from the Adafruit Funhouse project at https://learn.adafruit.com/adafruit-funhouse/getting-the-date-time which seemed to be common to several other projects too. Running at approx 2.30pm in Auckland the REPL output looked like

Fetching text from https://io.adafruit.com/api/v2/my-username/integrations/time/strftime?x-aio-key=my-key&tz=Pacific/Auckland&fmt=%25Y-%25m-%25d+%25H%3A%25M%3A%25S.%25L+%25j+%25u+%25z+%25Z
----------------------------------------
2023-09-14 14:30:12.491 257 4 +1200 NZST
----------------------------------------

which did match my localtime.

User mikeysklar on the Adafruit Forum noted that there's an open bug against the Adafruit_CircuitPython_AdafruitIO library in which io.receive_time() returns a time in UTC

https://github.com/adafruit/Adafruit_CircuitPython_AdafruitIO/issues/95

It looks like this behaviour was only intermittent when the bug was originally reported, but the IO_HTTP call in the Star Fragment code has been returning me a time 12 hours earlier than expected (i.e. a time that looks a lot like UTC) every time I've tried it lately, so possibly the bug has resurfaced and it's now consistently returning UTC.

The github issue notes that there's a workaround for the issue using a TZIO class (provided), so in the meantime I've had a go at adjusting the Star-Fragment code to use the workaround, i.e.

# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT

import os
import ssl
import time
import microcontroller
import board
import wifi
import socketpool
import adafruit_requests
import neopixel
import simpleio
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
from adafruit_io.adafruit_io import IO_HTTP

# latitude
lat = # *** update me ***
# longitude
long = # *** update me ***

# neopixel setup
NUMPIXELS = 16  # number of neopixels
BRIGHTNESS = 0.4  # A number between 0.0 and 1.0, where 0.0 is off, and 1.0 is max.
PIN = board.A3  # This is the default pin on the NeoPixel Driver BFF.

pixels = neopixel.NeoPixel(PIN, NUMPIXELS, brightness=BRIGHTNESS, auto_write=False)

# turn on NeoPixels on boot to check wiring
pixels.fill((255, 125, 0))
pixels.show()

# API request to open-meteo
weather_url = "https://api.open-meteo.com/v1/forecast?"
# pass latitude and longitude
# will return sunrise and sunset times
weather_url += "latitude=%d&longitude=%d&timezone=auto&daily=sunrise,sunset" % (lat, long)

#  connect to SSID
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))

pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())

pool = socketpool.SocketPool(wifi.radio)

# adafruit IO info
aio_username = os.getenv('aio_username')
aio_key = os.getenv('aio_key')
location = "Pacific/Auckland" # update this value, also could go into settings.toml

# function for adjusting for timezone
class TZIO(IO_HTTP):
    def receive_time(self, tz=location):
        path = self._compose_path("integrations/time/struct.json?tz={}".format(tz))
        time_struct = self._get(path)
        return time.struct_time(
            (
                time_struct["year"],
                time_struct["mon"],
                time_struct["mday"],
                time_struct["hour"],
                time_struct["min"],
                time_struct["sec"],
                time_struct["wday"],
                time_struct["yday"],
                time_struct["isdst"],
            )
        )

# io HTTP for getting the time from the internet
# io = IO_HTTP(aio_username, aio_key, requests) 
io = TZIO(aio_username, aio_key, requests) # updated with this line to use TZIO instead

def reset_on_error(delay, error):
    print("Error:\n", str(error))
    print("Resetting microcontroller in %d seconds" % delay)
    time.sleep(delay)
    microcontroller.reset()

# code continues as originally ...

and this looks like it's now working ok. The struct_time shown in the REPL output matches my local time now, and the lamp is back to brightening for sunset/switching on fully if it's already dark as expected.

Hope this helps in the meantime.

@that-fleps
Copy link

hmm, TL-DR version ...

  • I think the original Star-Fragment lamp code expects to receive localtime from AdafruitIO
  • the IO_HTTP call looks like it's currently returning UTC
  • the received time is used in the time-to-sunset and time-to-sunrise calculations, so depending on where you are in the world basing these on UTC might be no good
  • there's a (historic, intermittent) bug for io.receive_time() returning UTC instead of localtime open already

So, if the io.receive_time() bug has resurfaced and it's sending UTC instead of localtime, options might be:

I've added the TZIO workaround to the code on my lamp and it seems to be back working ok now. Debug messages in MuEdit/REPL show localtimes being returned and used for calculating time-to-sunset etc.

@clarkiej
Copy link
Author

clarkiej commented Sep 21, 2023

Thank you @that-fleps . I will add in your TZIO workaround and update on what happens in the morning. It is now after sunset, so I will let it run glowing and monitor the serial port, and update in the morning. I have no problems with the Sunset function, but for me sunrise is the issue. One hour before sunrise the lamp just turns off, no countdown. If there is a soft reboot after midnight and before sunrise, the lamp just reverts back to looking for sunset and ignores the upcoming sunrise.

@clarkiej
Copy link
Author

clarkiej commented Sep 21, 2023

I have let the lamp run till 1 hour before sunrise, and time is being calculated correctly, but unfortunately teh TZIO workaround does not correct the issue where instead of switching to counting down and darkening teh LED's one hour before sunrise, it still flips straight to turning the lamp off and tracking time till sunset :

4:56:32.323 -> pinging Open-Meteo
04:56:39.554 -> struct_time(tm_year=2023, tm_mon=9, tm_mday=22, tm_hour=4, tm_min=56, tm_sec=39, tm_wday=5, tm_yday=265, tm_isdst=0)
04:56:39.599 -> 1 hour(s) until sunrise
04:56:39.599 -> 14 minutes(s) until sunrise <-- all good tracking sunrise
04:56:39.599 -> 2023-09-22T06:10
04:56:39.599 -> struct_time(tm_year=2023, tm_mon=9, tm_mday=22, tm_hour=4, tm_min=56, tm_sec=39, tm_wday=5, tm_yday=265, tm_isdst=0)
04:56:39.599 ->
05:11:32.307 -> pinging Open-Meteo
05:11:39.413 -> struct_time(tm_year=2023, tm_mon=9, tm_mday=22, tm_hour=5, tm_min=11, tm_sec=38, tm_wday=5, tm_yday=265, tm_isdst=0)
05:11:39.474 -> 0 hour(s) until sunrise
05:11:39.474 -> 59 minutes(s) until sunrise
05:11:39.474 -> 2023-09-22T06:10
05:11:39.474 -> struct_time(tm_year=2023, tm_mon=9, tm_mday=22, tm_hour=5, tm_min=11, tm_sec=38, tm_wday=5, tm_yday=265, tm_isdst=0)
05:11:39.474 ->
05:11:39.474 -> star is off <-- an hour to go, oops no countdown, just turen lamp off
05:26:32.437 -> pinging Open-Meteo
05:26:39.650 -> struct_time(tm_year=2023, tm_mon=9, tm_mday=22, tm_hour=5, tm_min=26, tm_sec=39, tm_wday=5, tm_yday=265, tm_isdst=0)
05:26:39.716 -> 12 hour(s) until sunset
05:26:39.716 -> 48 minutes(s) until sunset <--- straight to tracking time till sunset
05:26:39.716 -> 2023-09-22T18:15
05:26:39.716 -> 0

Rebooting within the one hour before sunrise the lamp also disregards sunrise time, turns the lamp off and just goes to searching for sunset.

@clarkiej
Copy link
Author

Do we have an update on the inability to dim the lamp while counting down to sunrise?

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

5 participants