Skip to content

Commit e6e3bc4

Browse files
committed
Add bugfix that interrupted boot process
1 parent 234b186 commit e6e3bc4

File tree

5 files changed

+71
-74
lines changed

5 files changed

+71
-74
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# kwh_display
22

3-
43
*kwh_display* is a project developed in MicroPython aimed at creating a compact display solution using an ESP32 and an ILI9341 screen. The primary functionality of this project is to fetch electricity price data via API and display it on the screen.
54

65
![IMG_2749](https://github.com/user-attachments/assets/1165a0df-f645-466b-9224-a323dd0af6c2)
@@ -41,13 +40,13 @@ IO12 MISO
4140

4241
## ESP32
4342

44-
To use *kwh_display*, start by flashing the ESP32 with firmware `build-ESP32_GENERIC_250224.bin`, which is compiled from the [MicroPython](https://docs.micropython.org/en/latest/esp32/tutorial/intro.html) repository.
43+
To use *kwh_display*, start by flashing the ESP32 with firmware `build-ESP32_GENERIC_250228.bin`, which is compiled from the [MicroPython](https://docs.micropython.org/en/latest/esp32/tutorial/intro.html) repository.
4544

4645

4746
Erase and the flash the ESP32 using [esptool](https://github.com/espressif/esptool).
4847

4948
```
50-
esptool.py --port /dev/ttyUSB0 erase_flash && esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 build-ESP32_GENERIC_250224.bin
49+
esptool.py --port /dev/ttyUSB0 erase_flash && esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 build-ESP32_GENERIC_250228.bin
5150
```
5251

5352
Edit ```/kwh_display/config.json``` to match your preferred settings. You can customize the price interval to your preference (float). The default price settings are explained in the table below.

esp32/app/price.py

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,24 @@
55
import urequests
66
import ujson
77
import machine
8-
from datetime import datetime, timedelta, timezone
9-
10-
DAYS = (
11-
datetime.now(timezone(timedelta())),
12-
datetime.now(timezone(timedelta())) + timedelta(hours=24),
13-
)
8+
from datetime import timedelta
149

1510

1611
class ElectricityPriceAPI:
1712
"""
1813
Fetch spot prices.
1914
"""
2015

21-
def __init__(self):
22-
# type: () -> None
16+
def __init__(self, swe_localtime):
17+
# type: (datetime) -> None
2318
"""
2419
Initialize the ElectricityPriceAPI instance by loading the configuration.
2520
"""
2621
with open("config.json", "r") as f:
2722
self.config = ujson.load(f)
2823

24+
self.days = (swe_localtime, swe_localtime + timedelta(hours=24))
25+
2926
def get_url(self):
3027
# type: () -> list
3128
"""
@@ -40,11 +37,11 @@ def get_url(self):
4037

4138
return [
4239
f"{self.config['url']}{self.config['api']}{day.year:04}/{day.month:02}-{day.day:02}_{self.config['zone']}.json"
43-
for day in DAYS
40+
for day in self.days
4441
]
4542

46-
def get_url_tomorrow(self):
47-
# type: () -> str
43+
def get_url_tomorrow(self, swe_localtime):
44+
# type: (datetime) -> str
4845
"""
4946
Get the URL for the API for tomorrow which causes desplay to reboot.
5047
@@ -53,7 +50,7 @@ def get_url_tomorrow(self):
5350
5451
"""
5552

56-
tomorrow = datetime.now(timezone(timedelta())) + timedelta(hours=24)
53+
tomorrow = swe_localtime + timedelta(hours=24)
5754

5855
return f"{self.config['url']}{self.config['api']}{tomorrow.year:04}/{tomorrow.month:02}-{tomorrow.day:02}_{self.config['zone']}.json"
5956

@@ -64,36 +61,32 @@ def get_prices(self):
6461
"""
6562

6663
send_to_file = []
67-
failure_count = 0 # Initialize a counter for failures
68-
69-
for request, day in zip(self.get_url(), DAYS):
70-
try:
71-
print(f"Fetching JSON from: {request}")
72-
response = urequests.get(request)
73-
74-
if response.status_code == 200:
75-
send_to_file.append(
76-
{
77-
str((day.year, day.month, day.day)): [
78-
price["SEK_per_kWh"] for price in response.json()
79-
]
80-
}
81-
)
82-
response.close()
83-
else:
84-
print(
85-
f"Failed to fetch JSON, status code: {response.status_code}\nPrices might not be published yet or URL is incorrect."
86-
)
87-
response.close()
88-
failure_count += 1 # Increment the counter on failure
89-
if failure_count >= 2:
90-
print("Failed to fetch JSON twice, rebooting...")
91-
machine.soft_reset()
92-
continue
93-
94-
except OSError as e:
95-
print(f"An error occurred while fetching JSON: {e}\nRebooting...")
96-
machine.soft_reset()
64+
failure_count = 0
65+
66+
for request, day in zip(self.get_url(), self.days):
67+
68+
print(f"Fetching JSON from: {request}")
69+
response = urequests.get(request)
70+
71+
if response.status_code == 200:
72+
send_to_file.append(
73+
{
74+
str((day.year, day.month, day.day)): [
75+
price["SEK_per_kWh"] for price in response.json()
76+
]
77+
}
78+
)
79+
response.close()
80+
else:
81+
print(
82+
f"Failed to fetch JSON, status code: {response.status_code}\nPrices might not be published yet or URL is incorrect."
83+
)
84+
response.close()
85+
failure_count += 1 # Increment the counter on failure
86+
if failure_count == 2:
87+
print("Failed to fetch JSON twice, rebooting...")
88+
machine.soft_reset()
89+
continue
9790

9891
print(send_to_file)
9992
with open("prices.json", "a") as f:

esp32/app/swe_time.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
- Get the current local time in Sweden
77
"""
88

9+
import ntptime
10+
import machine
911
from datetime import datetime, timezone, timedelta
1012

1113

@@ -20,12 +22,36 @@ def __init__(self):
2022
Initialize the SweTime class and set the timezone.
2123
"""
2224

23-
# Swedish timezone offset
25+
print("Synchronizing time with NTP server...")
26+
ntptime.timeout = 3
27+
try:
28+
ntptime.settime()
29+
print("UTC time synchronized successfully!")
30+
except OSError as e:
31+
print(f"Failed to sync time: {e}")
32+
machine.soft_reset()
33+
34+
now = datetime.now(timezone(timedelta()))
35+
36+
print(f"UTC time is: {now}")
37+
38+
# Determine if DST is in effect
39+
self.offset = self._determine_offset(now)
40+
41+
def _determine_offset(self, now):
42+
# type: (datetime) -> int
43+
"""
44+
Determine the Swedish timezone offset considering DST.
45+
46+
Args:
47+
now (datetime): The current datetime.
48+
49+
Returns:
50+
int: The timezone offset.
51+
"""
2452
utc_offset = 1 # Standard time
2553
dst_offset = 2 # Daylight saving time
2654

27-
# Determine if DST is in effect
28-
now = datetime.now(timezone(timedelta()))
2955
month, day = now.month, now.day
3056
weekday = now.weekday()
3157

@@ -34,11 +60,9 @@ def __init__(self):
3460
or (month == 3 and day - weekday >= 25)
3561
or (month == 10 and day - weekday < 25)
3662
):
37-
offset = dst_offset
63+
return dst_offset
3864
else:
39-
offset = utc_offset
40-
41-
self.offset = offset
65+
return utc_offset
4266

4367
def swe_localtime(self):
4468
# type: () -> datetime

esp32/app/utils.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import ujson
1313
import network
14-
import ntptime
1514
import machine
1615
import urequests
1716
from datetime import timedelta
@@ -58,23 +57,6 @@ def hotspot():
5857
print(f"Access Point @ {ap.ifconfig()}")
5958

6059

61-
def ntp_sync():
62-
# type: () -> None
63-
"""
64-
Sync UTC time with NTP
65-
"""
66-
print("Synchronizing time with NTP server...")
67-
ntptime.timeout = 3
68-
for _ in range(3): # Try sync time three times before reset
69-
try:
70-
ntptime.settime()
71-
print("UTC time synchronized successfully!")
72-
return
73-
except OSError as e:
74-
print(f"Failed to sync time: {e}")
75-
machine.soft_reset()
76-
77-
7860
def fetch_prices_from_file(api, time):
7961
# type: (ElectricityPriceAPI, SweTime) -> tuple
8062
"""
@@ -136,10 +118,10 @@ def update_display(
136118

137119
# Checking if new prices are available.
138120
if hour >= 13 and prices_tomorrow is None:
139-
response = urequests.get(api.get_url_tomorrow())
121+
response = urequests.get(api.get_url_tomorrow(swe_localtime))
140122
if response.status_code == 200:
141123
print(
142-
f"New prices available, fetching from: {api.get_url_tomorrow()} and rebooting @ {hour}:{minute}:{second}..."
124+
f"New prices available, fetching from: {api.get_url_tomorrow(swe_localtime)} and rebooting @ {hour}:{minute}:{second}..."
143125
)
144126
machine.soft_reset()
145127
response.close()

esp32/main.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ def main():
3131

3232
else:
3333
utils.wifi()
34-
utils.ntp_sync()
3534

3635
time = SweTime()
3736
current_hour = time.swe_localtime().hour
3837

39-
api = ElectricityPriceAPI()
38+
api = ElectricityPriceAPI(time.swe_localtime())
4039
prices_today, prices_tomorrow = utils.fetch_prices_from_file(api, time)
4140

4241
gui = GUI()

0 commit comments

Comments
 (0)