# file : ntpclock_V10.py
# 23/11/23
# dht22 humidity/temp sensor, 2 displays, real time clock module.
# uses try-else except to connect to wifi. same for ntp time update.
# red-green indicator leds to indicate ntp update success
# RTC.datetime() acts on the internal machine rtc clock
# ds.datetime() acts on the rtc battery backup module.

from   machine import Pin, SPI, RTC, I2C, SoftI2C             
import max7219_8digit                                       
import network
import ntptime
from   time import *
import dht
import ds1302 
                             
hspi_ss    = Pin(15, Pin.OUT)
vspi_ss    = Pin(5, Pin.OUT)
redled     = Pin(17, Pin.OUT)    # indicates wifi ntp sync failed
greenled   = Pin(16, Pin.OUT)    # wifi ntp success
pin21 = Pin(21)
pin22 = Pin(22)
pin27 = Pin(27)

hspi        = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) # spi bus for max7219 display1
vspi       = SPI(2, 10000000, sck=Pin(18), mosi=Pin(23), miso=Pin(19))  # spi bus for max7219 display2

ds         = ds1302.DS1302(clk=pin21, dio=pin22 , cs=pin27)             # real time clock

display1   = max7219_8digit.Display(hspi, hspi_ss, 0)
display2   = max7219_8digit.Display(vspi, vspi_ss, 0)
d          = dht.DHT22(Pin(4, Pin.PULL_UP))                             # gpio4. Onewire Communication
UTC_OFFSET = 0 * 60 * 60                                                # GMT. change according to timezone. seconds from GMT
#UTC_OFFSET = 1 * 60 * 60                                               # BST. change according to timezone. seconds from GMT
ssid       = 'SSIDname'
station    = network.WLAN(network.STA_IF)            
passw      = "SECRETPASSWORD"

def LED1(message):
            display1.write_to_buffer(message)
            display1.display()

def LED2(message):
            display2.write_to_buffer(message)
            display2.display()

def connect_wifi(station, ssid, passw):
    station.active(True)
    count = 0
    while (not (station.isconnected())) and count < 3:       # keep looking until we connect
            print("waiting to Connect")
            station.ifconfig(('192.168.0.231', '255.255.255.0', '192.168.0.1', '194.168.4.100'))  # static IP config set
            count+=1
            try :
                station.connect(ssid, passw)
                station.active(True)
            except :
                print("Connection fail")              # if it fails try again
            else:
                print("Connection Success")
            finally: sleep(0.5)
            
def ntp_attempt(rtc,redled,greenled,ds):
        redled.value(1)
        greenled.value(1)  # both LEDs indicates we are trying to ntp update
        try:
                      ntptime.settime()                         # updates esp localtime() from NTP time from network
                      localtime(time() + UTC_OFFSET)            # adjust for BST/GMT  
        except:
                      print("ntp failed")                       # NTP FAIL
                      print("DS datetime is : ",DStoRTC())
                      rtc.init(DStoRTC())
                      greenled.value(0)
        else:                                                   
                      print("ntp  success")                     # NTP SUCCESS
                      print(localtime())
                      ds.date_time(rtc.datetime())           # updates ds3231.datetime() on DS3231 module
                      redled.value(0)
        finally:
                      print("Disconnecting Wifi")

def HourMinSec():
    hour   = '{:02d}'.format(localtime()[3])
    minute = '{:02d}'.format(localtime()[4])
    sec    = '{:02d}'.format(localtime()[5])
    return "{0}.{1}.{2}".format(hour,minute,sec)  

def DStoRTC():
    dstime  = ds.date_time()
    dstuple = (dstime[0],dstime[1],dstime[2],dstime[3],dstime[4],dstime[5],dstime[6],0)  # y,m,d,dow,h,min,sec,0
    print("ds.date_time from backup : ",dstuple)
    return(dstuple)

def check_sensors(sensor):
    while True:
        retry = 0
        while True:
            try:
                sensor.measure()
            except: pass
            else:
                H = str(round(sensor.humidity()))
                T = str(sensor.temperature()) + '\xb0'    # xb0 is degree sign
                return H,T

#MAIN PROGRAM
rtc = RTC()              # create instance of RTC object
greenled.value(0)
redled.value(0)
LED2('        ')
LED1('        ')
station.active(True)
connect_wifi(station, ssid, passw)
ntp_attempt(rtc,redled,greenled,ds)    
station.active(False)
counter = 0
while True:                         
    counter+=1
    counter = counter%30
    LED1(HourMinSec())
    print(counter)
    if counter%30==0: 
        H,T = check_sensors(d)
        LED2(T+' '+H)
    sleep(0.1)                                # checks/displays time every 1/10 second

# END OF PROGRAM



