# LTE

from network import LTE
import re
import time
import socket
import machine

from trap import * # 2.2.20


try:
    lte = LTE(debug=True)

except:
    print("LTE failed to initialize; rebooting...")
    machine.reset()



def disconnectLTE():
    global lte
    try:
        lte.disconnect()
        lte.detach()
        lte.deinit()

    except:
        lte = LTE()
        # no lte to disconnect


def connectLTE(deviceSettings, fnBoot, sdAccess=False, force=False): # 2.2.20 add DogRelay management   2.2.4 added settings
    global lte
    # disconnectLTE()
    machine.WDT(timeout=(2*60*1000)) # 2.2.20  2min  dogRelay compatible
    # file_errLog(0, "connectLTE", sdAccess) # 2.2.20
    try:
        #some carriers have special requirements, check print(lte.send_at_cmd("AT+SQNCTM=?")) to see if your carrier is listed.
        #when using verizon, use
        if not force and lte.isconnected():
            return True

        if force and lte.isconnected():
            lte.disconnect()

        try:
            lte.init(carrier=deviceSettings['lte_carrier'],debug=True) # 2.2.4b 'verizon' to deviceSettings['lte_carrier']  Options: verizon, standard

        except Exception as e:
            file_errLog(0, "connectLTE Function - cought error on lte.init(): " + str(e), sdAccess)
            file_errLog(0, "Reinitializing lte = LTE()", sdAccess)
            lte = LTE()
            lte.init(carrier=deviceSettings['lte_carrier'],debug=True)

        #when usint AT&T use,
        #lte.init(carrier=at&t)

        #some carriers do not require an APN
        #also, check the band settings with your carrier
        if (not lte.isattached()):
            ''' 2.2.20
            if deviceSettings['lte_carrier'] == 'standard': # 2.2.4b
                machine.WDT(timeout=(180*60*1000)) # is standard/teal give this longer to connect
                try:
                    lte.attach(apn='teal') # if lte_carrier is standard, APN needs to be set here:  lte.attache(apn="teal"), other wise lte.attach()
                except Exception as e:
                    print(str(e))
                    #file_errLog(0, "Failed to connect to LTE - " + str(e), sdAvailable)
                    machine.reset()
                # 2.2.18 machine.WDT(timeout=(1800*60*1000)) # is standard/teal give this longer to connect
                # lte.attach(apn='teal') # if lte_carrier is standard, APN needs to be set here:  lte.attache(apn="teal"), other wise lte.attach()
            else:
                lte.attach()
            '''
            # machine.WDT(timeout=(180*60*1000)) # 180min     is standard/teal give this longer to connect
            try:
                if deviceSettings['lte_carrier'] == 'standard': # 2.2.4b
                    lte.attach(apn='teal') # if lte_carrier is standard, APN needs to be set here:  lte.attache(apn="teal"), other wise lte.attach()
                else:
                    lte.attach()

            except Exception as e:
                # 2.2.20 print(str(e))
                file_errLog(0, "Fails to connect to LTE - " + str(e), sdAccess)  # 2.2.20
                # let the hardware whatdog do a hard reboot
                lte.send_at_cmd('AT+CFUN=0')
                time.sleep(2)
                lte.send_at_cmd('AT+CFUN=1')
                if deviceSettings['lte_carrier'] == 'standard': # 2.2.4b
                    lte.attach(apn='teal') # if lte_carrier is standard, APN needs to be set here:  lte.attache(apn="teal"), other wise lte.attach()
                else:
                    lte.attach()


            lteTimeout = 480 # 2.2.21  1min     # 2.2.20   21600 = 3Hour wait !! 240 = 2min - 480 4 minutes
            print("LTE attaching xxx",end='')
            file_errLog(0, "LTE attaching", sdAccess) # 2.2.21
            while not lte.isattached() and lteTimeout > 0:
                fnBoot(1) # 2.2.20    IamAlive()
                time.sleep_ms(500)
                lteTimeout = lteTimeout - 1  # 2.2.20  500
                if (lteTimeout == 240):
                    lte.send_at_cmd('AT+CFUN=0')
                    time.sleep(2)
                    lte.send_at_cmd('AT+CFUN=1')
                print('x',end='')

            #2.2.18  machine.WDT(timeout=(2*60*1000))
            if not lte.isattached():
                print(' failed.\n')
                # 5b print('Rebooting...')
                # 5b machine.reset()
                file_errLog(0, "Fails to attach LTE", sdAccess)  # 2.2.20
                return False
            else:
                #print(lte.send_at_cmd('AT!="fsm"')) # get the System FSM
                print(" attached.\n")
                file_errLog(0, "LTE attached", sdAccess)

        if not lte.isconnected():
            cidDef = {'verizon': 3, 'at&t': 2,  'standard': 1}
            if deviceSettings['lte_carrier']:
                lte.connect(cid=cidDef[deviceSettings['lte_carrier']])

        print("LTE connecting...",end='')
        file_errLog(0, "LTE connecting", sdAccess) # 2.2.21
        lteTimeout = 240 # 2.2.20  2min wait !!       15000
        while not lte.isconnected() and lteTimeout > 0:
            fnBoot(1) # 2.2.20    IamAlive()
            time.sleep_ms(500)
            lteTimeout = lteTimeout - 1 # 2.2.20   500
            print('.',end='')
            #print(lte.send_at_cmd('AT!="showphy"'))
            #print(lte.send_at_cmd('AT!="fsm"'))

        connected = lte.isconnected()
        if (connected):
            #print(socket.getaddrinfo('extranet.terrasls.com', 80))
            print("connected.\n")
            file_errLog(0, "LTE connected", sdAccess) # 2.2.21
            file_errLog(0, "Got DNS Servers from LTE: \t" + str(socket.dnsserver()), sdAccess)
            file_errLog(0, "Setting our own DNS Servers, because the Teal ones are in Paris")
            socket.dnsserver(0,'8.8.8.8')
            socket.dnsserver(1,'4.4.4.4')
            file_errLog(0, "Now using DNS servers: \t" + str(socket.dnsserver()), sdAccess)

        else:
            print("Failed to connect to LTE.\n")
            file_errLog(0, "Fails connecting LTE", sdAccess)  # 2.2.20

        # machine.WDT(timeout=(2*60*1000)) # 2.2.18
        return connected

    except OSError as e:
        # 2.2.20 print(str(e))
        file_errLog(0, "connectLTE Err - " + str(e), sdAccess)  # 2.2.20
        return False


def getEID():  # gets esim eid
    eid = None
    try:
        #stopLTE()
        lte.send_at_cmd('AT+CSIM=10,"0070000000"')
        lte.send_at_cmd('AT+CSIM=42,"01A4040010A0000005591010FFFFFFFF8900000200"')
        eid = lte.send_at_cmd('AT+CSIM=10,"81CA005A00"')[16:48]

    except:
        pass
        #startLTE()
    return eid


def infoLTE(lteEnabled, carrier=None):
    global lte

    if lteEnabled:
        try:
            res = lte.send_at_cmd("AT+CSQ")
            str = re.search(r'.*?Q: (.*),.*', res).group(1)
            rssi = -113+(int(str)*2)
            if (str == 99):
                rssi=0
            conn_data = { "route": "LTE", "details": { "carrier":carrier, "imei": lte.imei(), "iccid": lte.iccid(), "signalStrength": rssi }}
        except:
            rssi='?'
            conn_data = { "route": "LTE", "details": { "carrier":carrier, "details": "LTE busy" }}

    else:
        conn_data = { "route": "LTE", "details": { "carrier":carrier, "imei": lte.imei(), "iccid": lte.iccid() }  }

    if carrier == 'standard':
        eID = getEID()
        if eID:
            conn_data['details']['eid'] = eID

    return conn_data


def towerInfo():
    print(lte.send_at_cmd('AT+CEREG?').strip('\r\n\r\nOK').replace('\r\n',''))

#+SQNMONI - find more cells - must be attached
#+SQNINS - cell info - cant be attached
#+cereg=2 - set cell data info


def stopLTE():
    try:
        if lte.isconnected():
            lte.pppsuspend()
        return True

    except:
        return False

def startLTE():
    try:
        if not lte.isconnected():
            lte.pppresume()
        # lte = LTE()
        # connectLTE(force=True)
        return True

    except:
        return False
# if not attached AT+SQNINS=0 else AT+SQNMONI=7

# https://developers.google.com/maps/documentation/geolocation/overview#cell_tower_object
# missing homeMobileCountryCode(MCC), homeMobileNetworkCode(MNC), locationAreaCode(NID), mobileCountryCode(MCC), mobileNetworkCode(WCDMA)
#lte.send_at_command('AT!="RRC:showDetectedCell"')
#you might repeat that a few times, and it will show you detected cells.
#Also useful might be:
#lte.send_at_command('AT!="RRC:showSiConfig"')
#lte.send_at_command('AT!="RRC:showPlmn"')
#
def scanLTE(deviceSettings, fnBoot, sdAccess = False): # 2.2.20   2.2.4 added settings
    global lte

    try:
        at_test = lte.send_at_cmd('AT+SQNINS=?')
        if 'OK' in at_test:
            pass
        else:
            print("scanLTE Err: " + str(ValueError)) # 5b
            file_errLog(0, "scanLTE Err - " + str(ValueError), sdAccess)  # 2.2.20
            # 2.2.21  raise ValueError
            raise Exception("LTE - " + str(ValueError)) # 2.2.21

    except:
        scratch = "No reply from modem, or unable to process AT commands please reset modem and try again"
        print(scratch)
        file_errLog(0, scratch, sdAccess)  # 2.2.20
        lte.pppresume()
        return False

    # print ("scanLTE: " + str(at_test)) # 5b
    lteTimeout = 3 # 5b
    while  lteTimeout > 0: # 5b  True and lteTimeout < 0:
        band_scan = ['']
        lteTimeout = lteTimeout - 1   # 5b
        while band_scan == ['']:
            print('\r\nScanning networks', end='')
            band_scan = lte.send_at_cmd('AT+SQNINS=0').strip('\r\n\r\nOK').split('\r\n+SQNINS:')
            print(band_scan)
            for x in range(0,4):
                print('.', end='')
                fnBoot(1) # 2.2.20    IamAlive()
                time.sleep(0.25)

        if band_scan[0].split(',')[5] == '':
            print('\r\nCycling modem for band scan, please wait',end='')
            lte.deinit(reset=True)
            for x in range(0,5):
                print('.', end='')
                fnBoot(1) # 2.2.20    IamAlive()
                time.sleep(0.75)

            lte.init(carrier=deviceSettings['lte_carrier'], psm_period_value=0, psm_period_unit=LTE.PSM_PERIOD_DISABLED, psm_active_value=0, psm_active_unit=LTE.PSM_ACTIVE_DISABLED)
            print('\r\nReinitializing modem',end='')
            for x in range(0,5):
                print('.', end='')
                fnBoot(1) # 2.2.20    IamAlive()
                time.sleep(0.25)
        else:
            res = band_scan[0].strip('+SQNINS: ').strip('"').strip("'").split(',') # 5b
            print('Network scan complete. \n')
            return { "cellId": int(res[3].strip('"'),16), "locationAreaCode": int(res[4].strip('"'),16), "mobileCountryCode": int(res[5].strip('"')[:3]), "mobileNetworkCode": int(res[5].strip('"')[3:]), "age": 0, "signalStrength": float(res[9]) }

    # print("lteTimeout: " + str(lteTimeout) ) #5b
    return False # 5b
    # 5b   res = band_scan[0].strip('+SQNINS: ').strip('"').strip("'").split(',')
    # 5b return { "cellId": int(res[3].strip('"'),16), "locationAreaCode": int(res[4].strip('"'),16), "mobileCountryCode": int(res[5].strip('"')[:3]), "mobileNetworkCode": int(res[5].strip('"')[3:]), "age": 0, "signalStrength": float(res[9]) }
