###############################################################
# Based on the Pico Micropython repository at:
# https://github.com/raspberrypi/pico-micropython-examples/tree/master/i2c/1306oled
# fixed:
# https://stackoverflow.com/questions/75349005/oserror-2-when-using-urequests-module-in-mycropython
###############################################################

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
from SSD1306_Large import SSD1306_8x3
import imgfile
import io
import network   # handles connecting to WiFi
import urequests # handles making and servicing network requests
import utime
import random

#########################################
led_board = machine.Pin("LED", machine.Pin.OUT)
led_board.on()

# rele
rele1 = machine.Pin(0, machine.Pin.OUT)
rele2 = machine.Pin(1, machine.Pin.OUT)
rele3 = machine.Pin(2, machine.Pin.OUT)
rele4 = machine.Pin(3, machine.Pin.OUT)

pix_res_x  = 128 # SSD1306 horizontal resolution
pix_res_y = 64   # SSD1306 vertical resolution
sda_pin = 26
scl_pin = 27

# large display
display = SSD1306_8x3(Pin(sda_pin),Pin(scl_pin))
#########################################

def dcode(data):
    try: return data.decode('utf8')
    except: return data
    
def display_logo(oled,img):
    # Display image on the OLED
    oled.fill(0)
    oled.blit(img, 16, 10)
    oled.show()
  
def connect_to_network():
    led_board.toggle()
    # Connect to network
    wlan = network.WLAN(network.STA_IF)    
    wlan.active(True)
    if (wlan.isconnected()):
        return True
    # network name (ssid) and password:
    wlan.connect('Black***', '*********')
    utime.sleep_ms(5000)
    led_board.toggle()
    return wlan.isconnected()

def connect_info():
    led_board.toggle()
    # Connect to network
    wlan = network.WLAN(network.STA_IF)    
    wlan.active(True)
    for row in wlan.scan():
        if (dcode(row[0]) == 'Black****'):
            return row
    return ('','','',-1)

# login
def login_stems():
    led_board.toggle()
    url = "https://lb-eu.solinteg-cloud.com/gen2api/pc/user/login"
    headers = {"content-type": "application/json; charset=UTF-8"}
    json = {"account":"ja****@****.c**","pwd":"********************"}
    try:
        response = urequests.post(url, json=json, headers=headers)
        response_json = response.json()
        response_headers = response.headers
        response.close()
        #print(response_json)
        if (response_json["successful"] != True or response_json["errorCode"] != 0):
            return ""
        else:
            return response_json["body"][0]
    except OSError as e:
        print("Login to cloud FAILED")
        #import sys
        #sys.print_exception(e)
        #print(e)
        return ""

# get data from cloud
def station_overwiev(token):
    led_board.toggle()
    url = "https://lb-eu.solinteg-cloud.com/gen2api/station_monitor/getSingleStationData?stationId=*******"
    headers = {"Token": token}
    try:
        req = urequests.get(url, headers=headers)
        response_json = req.json()
        req.close()
        return response_json["body"]
    except OSError:
        print("Get SingleStationOverview FAILED")
        return None

def init_i2c(scl_pin, sda_pin):
    # Initialize I2C device
    i2c_dev = I2C(1, scl=Pin(scl_pin), sda=Pin(sda_pin), freq=400000)
    i2c_addr = [hex(ii) for ii in i2c_dev.scan()]
    if not i2c_addr:
        print('No I2C Display Found')
        sys.exit()
    else:
        print("I2C Address      : {}".format(i2c_addr[0]))
        print("I2C Configuration: {}".format(i2c_dev))
    return i2c_dev

def main_thread(oled):
    token = ""
    # Display a simple timer animation on the OLED
    start_time = utime.ticks_ms()

    while True:
        elapsed_time = (utime.ticks_diff(utime.ticks_ms(), start_time) // 1000) + 1

        led_board.toggle()
        
        while (token == ""):
            # connect to network
            while (not connect_to_network()):
                oled.fill(0)
                oled.text("Connecting...", 5, random.randint(5, 55))
                oled.show()
            #
            led_board.toggle()
            # login to st-ems cloud
            token = login_stems()
            if (token == ""):
                rele1.value(1)
                rele3.value(1)
                oled.fill(0)
                oled.text("Login - Error", 5, random.randint(5, 55))
                oled.show() # show the new text and image
                utime.sleep(30)
            else:
                oled.fill(0)
                oled.text("Login - OK", 5, 15)
                oled.show() # show the new text and image
                rele1.value(0)
                rele3.value(0)
        
        # download last data from st-ems cloud
        data = station_overwiev(token)
        
        if (data is None):
            rele1.value(1)
            rele3.value(1)
            token = ""
            oled.fill(0)
            oled.text("Disconnected", 15, 30)
            oled.show()
            utime.sleep(30)
        else:
            solar = data["pvNode"]["originData"]
            load = data["loadNode"]["originData"]
            # difference 
            diff = solar - load
            
            # battery have 98% and more
            if (data["soc"] >= 98):
                if (solar >= 1500):
                    rele2.value(0)
                    rele4.value(0)
                else:
                    rele2.value(0)
                    rele4.value(1)
            # battery have 80% and more
            elif (data["soc"] >= 80):
                if (solar > 2666):
                    rele2.value(0)
                    rele4.value(0)
                elif (solar > 1333):
                    rele2.value(0)
                    rele4.value(1)
                else:
                    rele2.value(1)
                    rele4.value(1)
            # battery have less than 80%
            else:
                rele2.value(1)
                rele4.value(1)
            
            
            display_logo(oled, imgfile.malina())
            utime.sleep(2)
            
            oled.fill(0)
            oled.blit(imgfile.malina(), 0, 0)
            oled.show()
            utime.sleep(2)
            
            oled.fill(0)
            oled.blit(imgfile.kojot(), 0, 0)
            oled.show()
            utime.sleep(2)
            
    
            viewData = data["meterNode"]["viewData"]
            print("Sit - CEZ", viewData)
            display.Clear()
            display.line1('Sit-CEZ')
            display.line2(viewData[:8])
            display.line3(viewData[8:16])
            display.Show()
            utime.sleep(5)
            led_board.toggle()
            
            viewData = data["batteryNode"]["viewData"]
            display.Clear()
            display.line1('Baterie')
            display.line2(viewData[:8])
            display.line3(str(data["soc"]) + "%")
            display.Show()
            #oled.fill(0)
            #oled.text("Baterie", 0, 5)
            #oled.text(data["batteryNode"]["viewData"], 5, 25)
            #oled.text(str(data["soc"]) + "%", 5, 45)
            #oled.show() # show the new text and image
            print("Baterie", data["soc"], "%")
            print("Baterie", data["batteryNode"]["viewData"])
            print("Baterie", data["batteryNode"]["originData"], "kW")
            utime.sleep(5)
            led_board.toggle()

            #oled.fill(0)
            #oled.text("FVE", 0, 5)
            #oled.text(data["pvNode"]["viewData"], 5, 25)
            #oled.show() # show the new text and image
            viewData = data["pvNode"]["viewData"]
            display.Clear()
            display.line1('FVE')
            display.line2(viewData[:8])
            display.line3(viewData[8:16])
            display.Show()
            print("FVE", data["pvNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()

            #oled.fill(0)
            #oled.text("Dum", 0, 5)
            #oled.text(data["loadNode"]["viewData"], 5, 25)
            #oled.show() # show the new text and image
            viewData = data["loadNode"]["viewData"]
            display.Clear()
            display.line1('Dum')
            display.line2(viewData[:8])
            display.line3(viewData[8:16])
            display.Show()
            print("Dum", data["loadNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()
            
            ############
            oled.fill(0)
            oled.text("Sit - CEZ", 0, 5)
            oled.text(data["meterNode"]["viewData"], 5, 25)
            oled.show()
            print("Sit - CEZ", data["meterNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()
            
            oled.fill(0)
            oled.text("Baterie", 0, 5)
            oled.text(data["batteryNode"]["viewData"], 5, 25)
            oled.text(str(data["soc"]) + "%", 5, 45)
            oled.show() # show the new text and image
            print("Baterie", data["soc"], "%")
            print("Baterie", data["batteryNode"]["viewData"])
            print("Baterie", data["batteryNode"]["originData"], "kW")
            utime.sleep(5)
            led_board.toggle()

            oled.fill(0)
            oled.text("FVE", 0, 5)
            oled.text(data["pvNode"]["viewData"], 5, 25)
            oled.show() # show the new text and image
            print("FVE", data["pvNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()

            oled.fill(0)
            oled.text("Dum", 0, 5)
            oled.text(data["loadNode"]["viewData"], 5, 25)
            oled.show() # show the new text and image
            print("Dum", data["loadNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()

            oled.fill(0)
            oled.text("Sit - CEZ", 0, 5)
            oled.text(data["meterNode"]["viewData"], 5, 25)
            oled.show()
            print("Sit - CEZ", data["meterNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()
            
            oled.fill(0)
            oled.text("Baterie", 0, 5)
            oled.text(data["batteryNode"]["viewData"], 5, 25)
            oled.text(str(data["soc"]) + "%", 5, 45)
            oled.show() # show the new text and image
            print("Baterie", data["soc"], "%")
            print("Baterie", data["batteryNode"]["viewData"])
            print("Baterie", data["batteryNode"]["originData"], "kW")
            utime.sleep(5)
            led_board.toggle()

            oled.fill(0)
            oled.text("FVE", 0, 5)
            oled.text(data["pvNode"]["viewData"], 5, 25)
            oled.show() # show the new text and image
            print("FVE", data["pvNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()

            oled.fill(0)
            oled.text("Dum", 0, 5)
            oled.text(data["loadNode"]["viewData"], 5, 25)
            oled.show() # show the new text and image
            print("Dum", data["loadNode"]["viewData"])
            utime.sleep(5)
            led_board.toggle()
            
### main_thread #end


def main():
    led_board.toggle()
    rele1.value(1)
    rele2.value(1)
    rele3.value(1)
    rele4.value(1)
    
    # oled init
    i2c_dev = init_i2c(scl_pin, sda_pin)
    # oled controller
    oled = SSD1306_I2C(pix_res_x, pix_res_y, i2c_dev)

    oled.fill(0) # clear the OLED
    oled.blit(imgfile.kojot(), 25, 0) # show the image at location (x=0,y=0)
    utime.sleep(5)
    led_board.toggle()

    start_x = 75 # start point for text in x-dir
    start_y = 12 # start point for text in y-dir
    lineskip = 15 # space between text in y-dir
    
    # connect to network
    while (not connect_to_network()):
        oled.fill(0)
        oled.text("Connecting...", 5, random.randint(5, 55))
        oled.show()
    oled.fill(0)
    oled.text("Wi-Fi - OK", 5, 15)
    oled.show() # show the new text and image
    info = connect_info()
    print(dcode(info[0]))
    print(info[3], "dBm")
    oled.text(dcode(info[0]), 5, 35)
    oled.text(str(info[3])+"dBm", 5, 55)
    oled.show() # show the new text and image
    
    main_thread(oled)

    # other functions
    # oled.poweron() # power on the OLED
    # oled.poweroff() # power off the OLED (save power)
    # oled.invert(1) # invert the colors from dark -> light, and light -> dark
    # oled.contrast(1) # lower brightness
    # oled.contrast(255) # increase brightness

if __name__ == '__main__':
    main()

BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module