Xinyuan-LilyGO / LilyGo-EPD-4-7-OWM-Weather-Display

Using the LilyGo EPD 4.7" display to show OWM Weather Data
65 stars 27 forks source link

UI.py failing when previously working fine. #1

Open dickydodds opened 1 year ago

dickydodds commented 1 year ago

In the last 2 weeks I have started getting this message below but unable to debug much as the esp seems to lockup in thonny after a minute of failing. Have re-flashed the code and re copied the files to no avail.

Received all weather data... (2052, 12, 9, 21, 37, 55, 0, 344) Traceback (most recent call last): File "", line 1, in File "", line 192, in File "ui.py", line 1036, in DisplayWeather File "ui.py", line 87, in DisplayGeneralInfoSection IndexError: list index out of range

Am running pre built binary version "MicroPython 609cd9e on 2022-04-13; ESP32 LILYGO EPD47 with ESP32" binfile name is LilyGo-MicroPython_esp32_LILYGO_EPD47_MPY-7c54b6428_IDF-e5f754b26c_B20220413_c06dc9a2fe.bin

lbuque commented 1 year ago

@dickydodds

Please try this binfile: https://github.com/Xinyuan-LilyGO/lilygo-micropython/suites/9514697728/artifacts/451759539

Modify main.py:

from json import load, loads
try:
    from time import localtime, ticks_ms, sleep
except:
    from time import localtime
try:
    import network
except:
    pass

try:
    from machine import deepsleep, ADC, Pin
except:
    pass

try:
    import usocket as socket
except:
    import socket

try:
    from framebuf1 import FrameBuffer
except:
    from framebuf import FrameBuffer

try:
    import urequests as requests
except ImportError:
    import requests

try:
    test = const(0)
except:
    def const(a):
        return a

wifi_signal = 0

SleepDuration = 60; # Sleep time in minutes, aligned to the nearest minute boundary, so if 30 will always update at 00 or 30 past the hour
WakeupHour    = 8;  # Don't wakeup until after 07:00 to save battery power
SleepHour     = 23; # Sleep after 23:00 to save battery power
CurrentHour = 0
CurrentMin = 0
CurrentSec = 0
Delta = 30
weather = None
forcast = None

max_readings = const(24)
Language = "EN"

def StartWiFi():
    global wifi_signal
    print("\r\nConnecting to: {}".format(ssid))
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
#     wlan.config(reconnects=3)
    wlan.connect(ssid, password)
    for _ in range(0, 60):
        sleep(1)
        if wlan.isconnected():
            break
    if wlan.isconnected():
        wifi_signal = wlan.status('rssi')
    print('network config:', wlan.ifconfig())
    return wlan.status()

def obtainWeatherData(request):
    units = "metric" if Units == "M" else "imperial"

    uri = '/data/2.5/{}?q={},{}&APPID={}&mode=json&units={}&lang={}'.format(
        request, City, Country, apikey, units, Language)
    if request != "weather":
        uri = '{}&cnt={}'.format(uri, str(max_readings))

    print("request uri: %s"%(uri))

    r = requests.get("http://{}{}".format(server, uri))
    DecodeWeather(request, r.json())
    r.close()
    if request == "weather" and weather is None:
        return False
    elif request == "forcast" and forcast is None:
        return False 
    return True
    #s = socket.socket()

    #ai = socket.getaddrinfo(server, 80)
    #print("Address infos:", ai)
    #addr = ai[0][-1]

    #print("Connect address:", addr)
    #s.connect(addr)

    #if use_stream:
        # MicroPython socket objects support stream (aka file) interface
        # directly, but the line below is needed for CPython.
        #s = s.makefile("rwb", 0)
        #s.send(bytearray("GET {} HTTP/1.0\r\n\r\n".format(url)))
        #print(s.read())
    #else:
    #s.send(bytearray("GET {} HTTP/1.0\r\n\r\n".format(uri)))
    #while True:
    #data = s.readline()
    #    if len(data) == 0:
    #        print("close socket")
    #        break
    #    print(data)
    #s.close()
    #DecodeWeather(request, "")

def DecodeWeather(request, data):
    if request == "weather":
        global CurrentMin
        global CurrentSec
        tm = localtime(data["dt"] + data["timezone"])
        CurrentMin = tm[4]
        CurrentSec = tm[5]
        global weather
        weather = data
    elif request == "forecast":
        global forcast
        forcast = data

def BeginSleep():
    # Some ESP32 have a RTC that is too fast to maintain accurate time, so add an offset
    SleepTimer = int((SleepDuration * 60 - ((CurrentMin % SleepDuration) * 60 + CurrentSec)) + Delta)
    print("Awake for : {:.3f}-secs".format(round(ticks_ms() / 1000.0, 3)))
    print("Entering {:d} (secs) of sleep time".format(SleepTimer))
    print("Starting deep-sleep period...")
    deepsleep(SleepTimer * 1000)

if __name__ == "__main__":
    import ui
    import gc
    from web import setupWEB
    adc = ADC(Pin(36))
    boot = Pin(35, Pin.IN)
    gc.enable()

    if boot.value() == 0:
        while True:
            setupWEB()

    f = open("config.json", "r")
    config = load(f)
    f.close()

    ssid = config["WLAN"]["ssid"]
    password = config["WLAN"]["password"]

    apikey     = config["OpenWeather"]["apikey"]
    server     = config["OpenWeather"]["server"]
    Country    = config["OpenWeather"]["country"]
    City       = config["OpenWeather"]["city"]
    Hemisphere = config["OpenWeather"]["hemisphere"]
    Units      = config["OpenWeather"]["units"]

    ntpServer = config["ntp"]["server"]
    Timezone = config["ntp"]["timezone"]

    buffer = bytearray(480 * 540)
    fb = FrameBuffer(buffer, 960, 540)
    fb.fill(255)
    ui.InitUI(fb)
    ui.Units = Units
    ui.Hemisphere = Hemisphere

    #if StartWiFi() == network.STAT_GOT_IP  and SetupTime() == True:
    if StartWiFi() == network.STAT_GOT_IP:
        WakeUp = False
        Attempts = 1
        RxWeather = False
        RxForecast = False
        while (RxWeather == False or RxForecast == False) and Attempts <= 2:
            # Try up-to 2 time for Weather and Forecast data
            if RxWeather == False:
                RxWeather = obtainWeatherData("weather")
            #if RxWeather == True:
            #    if WakeupHour > SleepHour:
            #        WakeUp = CurrentHour >= WakeupHour or CurrentHour <= SleepHour
            #    else:
            #        WakeUp = CurrentHour >= WakeupHour and CurrentHour <= SleepHour
            #    if WakeUp == False:
            #        BeginSleep()
            if RxForecast == False:
                RxForecast = obtainWeatherData("forecast")
            Attempts += 1
        print("Received all weather data...")

        if RxWeather and RxForecast:
            ui.DisplayWeather(weather, forcast, wifi_signal, adc.read()/4096.0 * 5)
            try:
                from epd import EPD47
                e = EPD47()
                e.power(True)
                e.clear()
                e.bitmap(buffer, 0, 0, 960, 540)
                e.power(False)
                del e
            except:
                print("The current parser is not micropython")
    BeginSleep()
dickydodds commented 1 year ago

Happy New Year :)

Thank you so much for looking into this and supplying a fix. I will try it out tomorrow for you and let you know.

Very much appreciated!!

Kind regards,

dicky

On Tue, 3 Jan 2023 at 10:05, lbuque @.***> wrote:

@dickydodds https://github.com/dickydodds

Please try this binfile: https://github.com/Xinyuan-LilyGO/lilygo-micropython/suites/9514697728/artifacts/451759539

Modify main.py:

from json import load, loadstry: from time import localtime, ticks_ms, sleepexcept: from time import localtimetry: import networkexcept: pass try: from machine import deepsleep, ADC, Pinexcept: pass try: import usocket as socketexcept: import socket try: from framebuf1 import FrameBufferexcept: from framebuf import FrameBuffer try: import urequests as requestsexcept ImportError: import requests try: test = const(0)except: def const(a): return a wifi_signal = 0 SleepDuration = 60; # Sleep time in minutes, aligned to the nearest minute boundary, so if 30 will always update at 00 or 30 past the hourWakeupHour = 8; # Don't wakeup until after 07:00 to save battery powerSleepHour = 23; # Sleep after 23:00 to save battery powerCurrentHour = 0CurrentMin = 0CurrentSec = 0Delta = 30weather = Noneforcast = None max_readings = const(24)Language = "EN" def StartWiFi(): global wifi_signal print("\r\nConnecting to: {}".format(ssid)) wlan = network.WLAN(network.STAIF) wlan.active(True)# wlan.config(reconnects=3) wlan.connect(ssid, password) for in range(0, 60): sleep(1) if wlan.isconnected(): break if wlan.isconnected(): wifi_signal = wlan.status('rssi') print('network config:', wlan.ifconfig()) return wlan.status() def obtainWeatherData(request): units = "metric" if Units == "M" else "imperial"

uri = '/data/2.5/{}?q={},{}&APPID={}&mode=json&units={}&lang={}'.format(
    request, City, Country, apikey, units, Language)
if request != "weather":
    uri = '{}&cnt={}'.format(uri, str(max_readings))

print("request uri: %s"%(uri))

r = requests.get("http://{}{}".format(server, uri))
DecodeWeather(request, r.json())
r.close()
if request == "weather" and weather is None:
    return False
elif request == "forcast" and forcast is None:
    return False
return True
#s = socket.socket()

#ai = socket.getaddrinfo(server, 80)
#print("Address infos:", ai)
#addr = ai[0][-1]

#print("Connect address:", addr)
#s.connect(addr)

#if use_stream:
    # MicroPython socket objects support stream (aka file) interface
    # directly, but the line below is needed for CPython.
    #s = s.makefile("rwb", 0)
    #s.send(bytearray("GET {} HTTP/1.0\r\n\r\n".format(url)))
    #print(s.read())
#else:
#s.send(bytearray("GET {} HTTP/1.0\r\n\r\n".format(uri)))
#while True:
#data = s.readline()
#    if len(data) == 0:
#        print("close socket")
#        break
#    print(data)
#s.close()
#DecodeWeather(request, "")

def DecodeWeather(request, data): if request == "weather": global CurrentMin global CurrentSec tm = localtime(data["dt"] + data["timezone"]) CurrentMin = tm[4] CurrentSec = tm[5] global weather weather = data elif request == "forecast": global forcast forcast = data def BeginSleep():

Some ESP32 have a RTC that is too fast to maintain accurate time, so add an offset

SleepTimer = int((SleepDuration * 60 - ((CurrentMin % SleepDuration) * 60 + CurrentSec)) + Delta)
print("Awake for : {:.3f}-secs".format(round(ticks_ms() / 1000.0, 3)))
print("Entering {:d} (secs) of sleep time".format(SleepTimer))
print("Starting deep-sleep period...")
deepsleep(SleepTimer * 1000)

if name == "main": import ui import gc from web import setupWEB adc = ADC(Pin(36)) boot = Pin(35, Pin.IN) gc.enable()

if boot.value() == 0:
    while True:
        setupWEB()

f = open("config.json", "r")
config = load(f)
f.close()

ssid = config["WLAN"]["ssid"]
password = config["WLAN"]["password"]

apikey     = config["OpenWeather"]["apikey"]
server     = config["OpenWeather"]["server"]
Country    = config["OpenWeather"]["country"]
City       = config["OpenWeather"]["city"]
Hemisphere = config["OpenWeather"]["hemisphere"]
Units      = config["OpenWeather"]["units"]

ntpServer = config["ntp"]["server"]
Timezone = config["ntp"]["timezone"]

buffer = bytearray(480 * 540)
fb = FrameBuffer(buffer, 960, 540)
fb.fill(255)
ui.InitUI(fb)
ui.Units = Units
ui.Hemisphere = Hemisphere

#if StartWiFi() == network.STAT_GOT_IP  and SetupTime() == True:
if StartWiFi() == network.STAT_GOT_IP:
    WakeUp = False
    Attempts = 1
    RxWeather = False
    RxForecast = False
    while (RxWeather == False or RxForecast == False) and Attempts <= 2:
        # Try up-to 2 time for Weather and Forecast data
        if RxWeather == False:
            RxWeather = obtainWeatherData("weather")
        #if RxWeather == True:
        #    if WakeupHour > SleepHour:
        #        WakeUp = CurrentHour >= WakeupHour or CurrentHour <= SleepHour
        #    else:
        #        WakeUp = CurrentHour >= WakeupHour and CurrentHour <= SleepHour
        #    if WakeUp == False:
        #        BeginSleep()
        if RxForecast == False:
            RxForecast = obtainWeatherData("forecast")
        Attempts += 1
    print("Received all weather data...")

    if RxWeather and RxForecast:
        ui.DisplayWeather(weather, forcast, wifi_signal, adc.read()/4096.0 * 5)
        try:
            from epd import EPD47
            e = EPD47()
            e.power(True)
            e.clear()
            e.bitmap(buffer, 0, 0, 960, 540)
            e.power(False)
            del e
        except:
            print("The current parser is not micropython")
BeginSleep()

— Reply to this email directly, view it on GitHub https://github.com/Xinyuan-LilyGO/LilyGo-EPD-4-7-OWM-Weather-Display/issues/1#issuecomment-1369584942, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARVORVAAVANFBBOW4M55UOLWQP2X5ANCNFSM6AAAAAAS2QOE5Q . You are receiving this because you were mentioned.Message ID: <Xinyuan-LilyGO/LilyGo-EPD-4-7-OWM-Weather-Display/issues/1/1369584942@ github.com>

dickydodds commented 1 year ago

Hi, Tried the bin and the modified main.py. It does not crash on the console anymore but I get no display on the lilygo T5 screen. The screen does a clear (goes black then white) and the console finishes with these messages - Icon name: 04d Icon name: 04d Icon name: 10n Icon name: 10n Icon name: 10n Icon name: 10n Icon name: 10n Icon name: 10d Icon name: 10d Icon name: 10d Icon name: 10n Icon name: 10n So it seems to be running but no display is shown.

I re-compiled python from the source (on git lilygo-micropython) just in case and uploaded that and it says its :- MicroPython c749c54 on 2023-01-04; T5-4.7 (spiram) with ESP32

Same as before - seems to run but no display. cheers, Dicky

On Tue, 3 Jan 2023 at 10:05, lbuque @.***> wrote:

@dickydodds https://github.com/dickydodds

Please try this binfile: https://github.com/Xinyuan-LilyGO/lilygo-micropython/suites/9514697728/artifacts/451759539

Modify main.py:

from json import load, loadstry: from time import localtime, ticks_ms, sleepexcept: from time import localtimetry: import networkexcept: pass try: from machine import deepsleep, ADC, Pinexcept: pass try: import usocket as socketexcept: import socket try: from framebuf1 import FrameBufferexcept: from framebuf import FrameBuffer try: import urequests as requestsexcept ImportError: import requests try: test = const(0)except: def const(a): return a wifi_signal = 0 SleepDuration = 60; # Sleep time in minutes, aligned to the nearest minute boundary, so if 30 will always update at 00 or 30 past the hourWakeupHour = 8; # Don't wakeup until after 07:00 to save battery powerSleepHour = 23; # Sleep after 23:00 to save battery powerCurrentHour = 0CurrentMin = 0CurrentSec = 0Delta = 30weather = Noneforcast = None max_readings = const(24)Language = "EN" def StartWiFi(): global wifi_signal print("\r\nConnecting to: {}".format(ssid)) wlan = network.WLAN(network.STAIF) wlan.active(True)# wlan.config(reconnects=3) wlan.connect(ssid, password) for in range(0, 60): sleep(1) if wlan.isconnected(): break if wlan.isconnected(): wifi_signal = wlan.status('rssi') print('network config:', wlan.ifconfig()) return wlan.status() def obtainWeatherData(request): units = "metric" if Units == "M" else "imperial"

uri = '/data/2.5/{}?q={},{}&APPID={}&mode=json&units={}&lang={}'.format(
    request, City, Country, apikey, units, Language)
if request != "weather":
    uri = '{}&cnt={}'.format(uri, str(max_readings))

print("request uri: %s"%(uri))

r = requests.get("http://{}{}".format(server, uri))
DecodeWeather(request, r.json())
r.close()
if request == "weather" and weather is None:
    return False
elif request == "forcast" and forcast is None:
    return False
return True
#s = socket.socket()

#ai = socket.getaddrinfo(server, 80)
#print("Address infos:", ai)
#addr = ai[0][-1]

#print("Connect address:", addr)
#s.connect(addr)

#if use_stream:
    # MicroPython socket objects support stream (aka file) interface
    # directly, but the line below is needed for CPython.
    #s = s.makefile("rwb", 0)
    #s.send(bytearray("GET {} HTTP/1.0\r\n\r\n".format(url)))
    #print(s.read())
#else:
#s.send(bytearray("GET {} HTTP/1.0\r\n\r\n".format(uri)))
#while True:
#data = s.readline()
#    if len(data) == 0:
#        print("close socket")
#        break
#    print(data)
#s.close()
#DecodeWeather(request, "")

def DecodeWeather(request, data): if request == "weather": global CurrentMin global CurrentSec tm = localtime(data["dt"] + data["timezone"]) CurrentMin = tm[4] CurrentSec = tm[5] global weather weather = data elif request == "forecast": global forcast forcast = data def BeginSleep():

Some ESP32 have a RTC that is too fast to maintain accurate time, so add an offset

SleepTimer = int((SleepDuration * 60 - ((CurrentMin % SleepDuration) * 60 + CurrentSec)) + Delta)
print("Awake for : {:.3f}-secs".format(round(ticks_ms() / 1000.0, 3)))
print("Entering {:d} (secs) of sleep time".format(SleepTimer))
print("Starting deep-sleep period...")
deepsleep(SleepTimer * 1000)

if name == "main": import ui import gc from web import setupWEB adc = ADC(Pin(36)) boot = Pin(35, Pin.IN) gc.enable()

if boot.value() == 0:
    while True:
        setupWEB()

f = open("config.json", "r")
config = load(f)
f.close()

ssid = config["WLAN"]["ssid"]
password = config["WLAN"]["password"]

apikey     = config["OpenWeather"]["apikey"]
server     = config["OpenWeather"]["server"]
Country    = config["OpenWeather"]["country"]
City       = config["OpenWeather"]["city"]
Hemisphere = config["OpenWeather"]["hemisphere"]
Units      = config["OpenWeather"]["units"]

ntpServer = config["ntp"]["server"]
Timezone = config["ntp"]["timezone"]

buffer = bytearray(480 * 540)
fb = FrameBuffer(buffer, 960, 540)
fb.fill(255)
ui.InitUI(fb)
ui.Units = Units
ui.Hemisphere = Hemisphere

#if StartWiFi() == network.STAT_GOT_IP  and SetupTime() == True:
if StartWiFi() == network.STAT_GOT_IP:
    WakeUp = False
    Attempts = 1
    RxWeather = False
    RxForecast = False
    while (RxWeather == False or RxForecast == False) and Attempts <= 2:
        # Try up-to 2 time for Weather and Forecast data
        if RxWeather == False:
            RxWeather = obtainWeatherData("weather")
        #if RxWeather == True:
        #    if WakeupHour > SleepHour:
        #        WakeUp = CurrentHour >= WakeupHour or CurrentHour <= SleepHour
        #    else:
        #        WakeUp = CurrentHour >= WakeupHour and CurrentHour <= SleepHour
        #    if WakeUp == False:
        #        BeginSleep()
        if RxForecast == False:
            RxForecast = obtainWeatherData("forecast")
        Attempts += 1
    print("Received all weather data...")

    if RxWeather and RxForecast:
        ui.DisplayWeather(weather, forcast, wifi_signal, adc.read()/4096.0 * 5)
        try:
            from epd import EPD47
            e = EPD47()
            e.power(True)
            e.clear()
            e.bitmap(buffer, 0, 0, 960, 540)
            e.power(False)
            del e
        except:
            print("The current parser is not micropython")
BeginSleep()

— Reply to this email directly, view it on GitHub https://github.com/Xinyuan-LilyGO/LilyGo-EPD-4-7-OWM-Weather-Display/issues/1#issuecomment-1369584942, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARVORVAAVANFBBOW4M55UOLWQP2X5ANCNFSM6AAAAAAS2QOE5Q . You are receiving this because you were mentioned.Message ID: <Xinyuan-LilyGO/LilyGo-EPD-4-7-OWM-Weather-Display/issues/1/1369584942@ github.com>

dickydodds commented 1 year ago

Update on the no display. noticed in UI.py you clear the display and display the bitmap. So I commented out the try catch in main.py and ran main,py again. I still don't get a display but I got more output as follows - Icon name: 10d Icon name: 10d Icon name: 04n �W���for : 80.773-secs Entering 2248 (secs) of sleep time Star ing Cheers, dicky

lbuque commented 1 year ago

@dickydodds Yes, I'm running on T5-4.7, but it's working on T5-4.7 S3.

This repo is currently due to some copyright issues, we will delete it in the near future and try to write a new one.

dickydodds commented 1 year ago

Thanks for the update, much appreciated. Dicky

On Mon, 6 Feb 2023, 08:54 lbuque, @.***> wrote:

@dickydodds https://github.com/dickydodds Yes, I'm running on T5-4.7, but it's working on T5-4.7 S3.

This repo is currently due to some copyright issues, we will delete it in the near future and try to write a new one.

— Reply to this email directly, view it on GitHub https://github.com/Xinyuan-LilyGO/LilyGo-EPD-4-7-OWM-Weather-Display/issues/1#issuecomment-1418724177, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARVORVFLM6M4ACEQLZYCPHDWWC357ANCNFSM6AAAAAAS2QOE5Q . You are receiving this because you were mentioned.Message ID: <Xinyuan-LilyGO/LilyGo-EPD-4-7-OWM-Weather-Display/issues/1/1418724177@ github.com>

lbuque commented 1 year ago

@dickydodds About using T5-4.7 (ESP32) to write out framebuf normally, #2 gives a good explanation.