import time
import machine
import utime
from umqtt.simple import MQTTClient
from machine import RTC,I2C
import micropython
import esp
import uasyncio
import gc
import ubinascii
import sys
import onewire, ds18x20
import mqtt_cfg
try:
  import urequests as requests
except:
  import requests
bStartup = True
gc.collect()
esp.osdebug(None)
gpioNum = 22
sTemp = machine.Pin(gpioNum)
ds = ds18x20.DS18X20(onewire.OneWire(sTemp))
tSensors = ds.scan()
displayActive = False
def _to_romcode_string(bytearray_romcode):
    string_hex_list = [str(ubinascii.hexlify(bytes([el])), 'utf8') for el in bytearray_romcode]
    romcode_str = ''.join(string_hex_list)
    return romcode_str
def getTempNow(sDevice):
    ds.convert_temp()
    return ds.read_temp(sDevice)
def get_id():
    url = 'https://www.uuidtools.com/api/generate/v4'
    response = requests.get(url)
    if response.status_code == 200:
        uid = response.text[2:-2]
        print("UID = %s" % uid)
        return uid
    else:
        print('Error')
        print(response.text)  
        return '_n_a'
def get_localtime(bFromNtp=False):
    if bFromNtp:
        import ntptime
        ntptime.settime()
    else:
        url = 'http://worldtimeapi.org/api/timezone/Europe/Brussels.txt'
        response = requests.get(url)
        if response.status_code == 200:
            dtDict = response.text.split('\n')
            now = dtDict[2].split(':',1)[1].strip()
            dow = dtDict[3].split(':')[1].strip()
            datePart, timePart = now.split('T')
            year = int(datePart.split('-')[0])
            month = int(datePart.split('-')[1])
            day = int(datePart.split('-')[2])
            hour = int(timePart.split(':')[0])
            minute = int(timePart.split(':')[1])
            second = int(timePart.split(':')[2].split('.')[0])
            subsecond = int(timePart.split('.')[1].split('+')[0])    
            rtc = RTC()
            rtc.init((year,month,day,dow,hour,minute,second,subsecond))
        else:
            print('Error')
            print(response.text)
def restart_and_reconnect():
    print('Failed to connect to InfluxDB. Reconnecting...')
    utime.sleep_ms(15)
    if displayActive:
        try:
            display.init_display()
        except:
            pass
    #machine.reset()
  
async def run():
    last_message = 0
    message_interval = mqtt_cfg.message_interval
    print("Syncing local time...", end='')
    try:
        get_localtime(bFromNtp=False)
    except:
        try:
            get_localtime(bFromNtp=False)
        except:
            restart_and_reconnect()
    print("done.")
    print("Generating client ID...", end='')
    pub_client_id = 'FamClaes_%s_%s' % (get_id(),ubinascii.hexlify(machine.unique_id()).decode())
    print(pub_client_id)
    print('Start publishing...')
    bStartup = True
    dctClients={}
    now = utime.localtime()
    ts = "{:02d}/{:02d}/{} {:02d}:{:02d}:{:02d}".format(now[2],now[1],now[0],now[3],now[4],now[5])
    tSensors = ds.scan()
    for s in tSensors:
        aRomCode = _to_romcode_string(s)
        print ('Found sensor: %s' % aRomCode)
    while True:
        #Niet elke keer chekcen voor additionele sensors? Mss om de 30 minuten? Of mss enkel bij reboot?
        if (time.time() - last_message) > message_interval or bStartup == True:
            if bStartup:
                bStartup = False
            tSensors = ds.scan()
            ts = "{:02d}/{:02d}/{} {:02d}:{:02d}:{:02d}".format(now[2],now[1],now[0],now[3],now[4],now[5])
            tSensors = ds.scan()
            for s in tSensors:
                aRomCode = _to_romcode_string(s)
                #print ('Found sensor: %s' % aRomCode)
                tempCelcius = str(getTempNow(s))
                for srvMosq in mqtt_cfg.activeServers:
                    topic_pub = b"%s" % (aRomCode)
                    print('Read %s from %s' % (tempCelcius, topic_pub))
            utime.sleep(2)
            last_message = time.time()                       
            utime.sleep(2)
if __name__ == '__main__':
    try:
        uasyncio.run(run())
        oled.poweroff()
    except KeyboardInterrupt:
        os.exit(250)
    except Exception as e:
        print ("Encountered error ", e.args, "...rebooting")
        sys.print_exception(e)    
        restart_and_reconnect()