Example #1
0
def cistyCipshut():
    try:  #funguje len ak bezi thread serialRead()
        #CIPSHT:
        #najprv vymaz queue
        if queueVypni.full():
            queueVypni.get()

        serialPort.write(prikazyNaVypni[1])
        try:
            if queueVypni.get(timeout=4) == 'cipshutOK':
                log.info("AT+CIPSHUT > SHUT OK.")
                return 0
            else:
                log.error(
                    "postup nebol dodrzany alebo sa vyskytla chyba, restartuj internet"
                )
                return 1
        except:
            log.error("Nepodarilo sa.")
            return 1

    except queue.Empty:
        log.exception("serialRead neodpovedal nacas!")
    except:
        log.exception("EXCEPTION!")
Example #2
0
def telefonuj():
    try:
        log.info("Telefonujem!")
        volajTelefon = b'ATD' + ZP.TEL_CISLO + b';\r\n'
        zlozTelefon = b'ATH\r\n'

        serialPort.write(
            zlozTelefon
        )  #najprv zloz telefon lebo niekedy sa moze stat, ze ostane vysiet z predchadzajuceho hovoru
        time.sleep(0.1)
        serialPort.write(volajTelefon)
        time.sleep(60)  #8 sekund vytaca a zvoni 52 sekund
        serialPort.write(zlozTelefon)
        return 0
    except:
        log.exception("EXCEPTION!")
        return 1
Example #3
0
def posliSpravu(response):
    #this function, in order to work properly, has to follow prijmiSpravu() function in serial logic
    for pocetZlyhani in range(3):
        try:
            #initiate sending:
            serialPort.write(prikazyPosliSpravu[0])
            #cakaj na ODOSIELANIE:
            if queueSocket.get(timeout=10) == 'cipsendOK':
                serialPort.write(bytes(response, 'utf-8') + b'\x1a\r\n')
            else:
                log.error("Serial neprijal spravu na odoslanie.")
                return 1  #AdapterManager o tom upozorni ale tento pripad zatial ignorujeme.
            #cakaj na SEND OK:
            if queueSocket.get(timeout=10) == 'sendOK':
                log.info("Sprava odoslana.")\
        #serialPort.write(prikazyPosliSpravu[1]) #ignoruj, socket sa zatvara automaticky

            else:
                log.critical(
                    "Serial odpoved na odoslanie spravy je necakana. SERVER neodpoveda?!"
                )
                return 1  #AdapterManager o tom upozorni ale tento pripad zatial ignorujeme.
            #cakaj na closed:
            if queueSocket.get(timeout=10) == 'closed':
                log.debug("Socket closed.")
                cistyCipshut()
            else:
                log.warning("Socket closed didn't work but I ignore it.")

            #ak nenastal problem, return 0:
            return 0  #message was sent at this point

        except queue.Empty:
            if pocetZlyhani >= 2:  #only when we tried 3 times, restart adapter
                ZP.adapterJob_prioDeq.put(
                    'pwrKeyAdapter', delete=False
                )  #keep other jobs pending as we are just fixing something
                return 1  #AdapterManager o tom upozorni ale tento pripad zatial ignorujeme.
            log.exception(
                "Spravu sa asi nepodarilo odoslat - serial neodpoveda. Pokus "
                + str(pocetZlyhani) + "/3. Potom restartujem.")
Example #4
0
def vypniInternet():
    try:  #funguje len ak bezi thread serialRead()

        #VYPNI INTERNET:
        #najprv vymaz queue
        if queueVypni.full():
            queueVypni.get()

        log.info("Vypinam internet...")
        serialPort.write(prikazyNaVypni[0])
        try:
            if queueVypni.get(timeout=3) == 'cipcloseOK':
                log.debug("cipclose OK")
                serialPort.write(prikazyNaVypni[1])  #cipshut
            else:
                log.error(
                    "A postup nebol dodrzany alebo sa vyskytla chyba, restartuj internet"
                )
                return 1
        except:
            log.error("Nepodarilo sa.")
            return 1

        try:
            if queueVypni.get(timeout=5) == 'cipshutOK':
                log.info("AT+CIPSHUT > SHUT OK.")
                return 0
            else:
                log.error(
                    "postup nebol dodrzany alebo sa vyskytla chyba, restartuj internet"
                )
                return 1
        except:
            log.error("Nepodarilo sa.")
            return 1

    except queue.Empty:
        log.exception("serialRead neodpovedal nacas!")
    except:
        log.exception("EXCEPTION!")
Example #5
0
def zapniInternet():
    global internetByMalBytPripraveny

    try:  #funguje len ak bezi thread serialRead()

        #ZAPNI INTERNET
        if queueZapni.full():
            queueZapni.get()

        log.info("Zapinam internet...")
        serialPort.write(prikazyNaZapni[0])
        if queueZapni.get(timeout=5) == 'csttOK':
            serialPort.write(prikazyNaZapni[1])
        else:
            log.error(
                "postup nebol dodrzany alebo sa vyskytla chyba, restartuj internet"
            )
            return 1
        if queueZapni.get(timeout=5) == 'ciicrOK':
            serialPort.write(prikazyNaZapni[2])
        else:
            log.error(
                "postup nebol dodrzany alebo sa vyskytla chyba, restartuj internet"
            )
            return 1
        if queueZapni.get(timeout=5) == 'cifsrOK':
            log.info("Internet zapnuty!")
            internetByMalBytPripraveny = True
            return 0
        else:
            log.error(
                "postup nebol dodrzany alebo sa vyskytla chyba, restartuj internet"
            )
            return 1

    except queue.Empty:
        log.exception("serialRead neodpovedal nacas!")
    except:
        log.exception("EXCEPTION!")
Example #6
0
def uspiRpi(trvanieSpanku, pociatok):
    try:
        '''tato funkcia:
    1.vypina RPI a zapise default odpocet
    2.uspava RPI a odrata dlzku spanku z odpoctu
    3.len chvilu caka(ak sa neoplati spat alebo ide o DEBUG mod), odrata dlzku cakania z odpoctu
    '''
        #1. vypni RPI:
        if trvanieSpanku == None:
            log.info(
                "Vypinam RPI natrvalo! Zapisujem defaultne hodnoty do konfig.json a odpocet.json."
            )

        #2. uspi pomocou WittyPi:
        else:
            trvanieSpanku = round(trvanieSpanku)
            systemTimeToRtc()
            time.sleep(4)
            #pociatok je nadiktovany uz v Main pri vypocte oddychu
            casZapnutia = pociatok + datetime.timedelta(
                seconds=trvanieSpanku)  #datetime object
            if trvanieSpanku < 60:  #sekundova schedule sluzi len pre RPI restart
                wittySched = "?? ?? ?? " + str(casZapnutia.second)
                log.info("Pozadovany spanok je " + str(trvanieSpanku) +
                         "s. Pociatok: " + str(pociatok) +
                         ". Zapisujem Witty Startup Time:" + str(wittySched))
            elif trvanieSpanku < 3600:  #minutova schedule
                wittySched = "?? ?? " + str(casZapnutia.minute) + " " + str(
                    casZapnutia.second)
                log.info("Pozadovany spanok je " + str(trvanieSpanku) +
                         "s. Pociatok: " + str(pociatok) +
                         ". Zapisujem Witty Startup Time:" + str(wittySched))
            else:  #hodinova schedule
                BUG = 2  #v set_startup_time.sh je nejaka chyba a zapisany spanok ma inu hodnotu ako ten pozadovany, toto to opravi
                #to co sa zobrazuje vo wittyPi.sh skripte je to co wittyPi respektuje
                wittySched_bezBUGU = "?? " + str(casZapnutia.hour) + " " + str(
                    casZapnutia.minute) + " " + str(casZapnutia.second)
                wittySched = "?? " + str(casZapnutia.hour - BUG) + " " + str(
                    casZapnutia.minute) + " " + str(casZapnutia.second)
                log.info("Pozadovany spanok je " + str(trvanieSpanku) +
                         "s. Pociatok: " + str(pociatok) +
                         ". Zapisujem Witty Startup Time:" +
                         str(wittySched_bezBUGU))
            startupTime(wittySched)

        #turn off GPS if it is running
        active_threads = [x.name for x in threading.enumerate()]
        if 'MerajGps' in active_threads:
            log.debug("Vypinam spustene GPS.")
            Meraj.vypni_GPS()
            time.sleep(5)

        #in case we are in debug mode, dont shut down RPI, just stop the program
        debugModeON = isDebugMode()
        log.debug("debug?: " + str(debugModeON))
        if (debugModeON):
            log.debug("Debug je zapnuty, nevypinam RPI")
        else:
            log.debug("RPI sa vypina!")
            vypniRpiPomocouWittyPi()

        sys.exit(0)

    except:
        log.exception("EXCEPTION!")
Example #7
0
def praca():

    #spusti serial reader v predstihu:
    threading.Thread(target=reader.read, name='serialRead',
                     daemon=True).start()

    pocet_pokusov = 3

    while True:
        try:
            q_get = ZP.adapterJob_prioDeq.get()

            log.info("pracujem na: '" + str(q_get) + "', zbytok Q:" +
                     str(ZP.adapterJob_prioDeq.deqList))

            if q_get == 'pripojAdapter':
                worker.pripojAdapter()
                assistant.zarucOdpAPripojenie()

            elif q_get == 'restartujInternet':
                worker.restartujInternet()

            elif q_get == 'telefonuj':
                #ak sa nepodari ani pripravit telefonovanie tak ho urcite vloz naspat do queue
                if assistant.pripravTelefonovanie() == 0:
                    #telefonuj:
                    #a v pripade, ze sa nepodari tak vloz telefonovanie naspat do queue
                    if worker.telefonuj() == 1:
                        ZP.adapterJob_prioDeq.put('telefonuj')
                else:
                    ZP.adapterJob_prioDeq.put('telefonuj')

            elif q_get == 'posta':
                ZP.AdapterNeodosielaSpravu = False
                assistant.pripravOdosielanie()
                prijataSprava = worker.prijmiSpravu()  #neosekana
                #if no new instructions were received, just reply with current KonfigD
                if prijataSprava == 1:
                    log.error(
                        "Sprava neodoslana (server prestal reagovat alebo AlreadyConnect error). Restartujem internet !"
                    )
                    if (ZP.troubleMonitor.alreadyConnect_tryAgain
                        ):  #try again if required.
                        log.error(
                            "Novy pokus cislo" +
                            str(ZP.troubleMonitor.alreadyConnect_count) + "/" +
                            str(ZP.troubleMonitor.alreadyConnect_MAXcount))
                        #restartuj internet kedze alreadyConnect sa len tak nevyriesi..
                        ZP.adapterJob_prioDeq.put(
                            'restartujInternet', delete=False
                        )  #do not delete other jobs - keep them pending as we are just fixing something
                        if specialne.MessageNotInAdapterQueue():
                            ZP.adapterJob_prioDeq.put("posta")
                    else:
                        log.error(
                            "Pocet pokusov vyprsal. Pravdepodobne nie je server vobec dostupny. Nastavujem informovanie na minimalne 3 min."
                        )
                        #load the property, it will be used at the beginning of the next main run
                        ZP.troubleMonitor.konfigD_modifiedProperties = ZP.troubleMonitor.alreadyConnect_konfigD
                        ZP.troubleMonitor.alreadyConnect_tryAgain = True  #(reset) opakuj pokusy pri dalsich korespondenciach

                elif prijataSprava == 2:
                    log.error("Sprava neodoslana (server unreachable) !")
                    if (ZP.troubleMonitor.serverUnreachable_tryAgain
                        ):  #try again if required.
                        log.error(
                            "Novy pokus cislo" +
                            str(ZP.troubleMonitor.serverUnreachable_count) +
                            "/" +
                            str(ZP.troubleMonitor.serverUnreachable_MAXcount))
                        if specialne.MessageNotInAdapterQueue():
                            ZP.adapterJob_prioDeq.put("posta")
                    else:
                        log.error("Pocet pokusov vyprsal, vzdavam to!")
                        ZP.troubleMonitor.serverUnreachable_tryAgain = True  #opakuj pokusy pri dalsich korespondenciach

                elif prijataSprava == None:
                    log.critical(
                        "Socket vratil prijatu spravu NONE, skontroluj co to je za problem."
                    )
                else:
                    if len(
                            prijataSprava
                    ) < 6:  #no new instructions is something like this b'\x00\x00\r\n'
                        log.debug("Neprisla sprava.")
                        prijataSprava = None  #neviem uz preco...
                        odpoved = korespondencia.sformulujOdpoved(ZP.konfigD)
                        #if new instructions were received, reply with updated konfigD(dummy for this moment) first.
                    else:
                        log.debug("Prijata sprava zpracovana: " +
                                  str(prijataSprava))
                        prijataSprava_obj = korespondencia.Rozbal(
                            prijataSprava)
                        #ak prisla sprava, zapis konfigy do txt a z toho txt nacitaj premenne. Nenacitavaj premenne znova v kazdom While loope ale len ak prisla sprava.
                        #nacitaj ZP.konfigD a odpocetD (ak neprisla sprava tak nastavenia su 1.defaultne alebo 2.relax mod)
                        print("ZP.konfigD PRED:", ZP.konfigD)
                        konfigD_dummy = specialne.aktualizujKonfigDSpravou(
                            prijataSprava_obj)
                        print("konfigD_dummy", konfigD_dummy)
                        print("ZP.konfigD PO:", ZP.konfigD)
                        with ZP.prijataSprava_dequelock:
                            ZP.prijataSprava_deque.append(
                                (prijataSprava_obj, konfigD_dummy))
                        #loguj data z prijatej spravy
                        log.info("Prijata sprava!: "+ " " + str(prijataSprava_obj.intervalMerTep) + " " + str(prijataSprava_obj.intervalMerGps) + " " + str(prijataSprava_obj.intervalInfTep)  \
                         + " " + str(prijataSprava_obj.intervalInfGps) + " " + str(prijataSprava_obj.tolerLow) + " " + str(prijataSprava_obj.tolerHigh) + " " + str(prijataSprava_obj.onOffAlarmPark) + " " + str(prijataSprava_obj.aktBoxy))

                        odpoved = korespondencia.sformulujOdpoved(
                            konfigD_dummy)
                    if worker.posliSpravu(odpoved) == 1:
                        log.critical(
                            'Nepodarilo sa odoslat spravu. Necakana chyba!')
                    else:
                        pass  #odosle spravu

                ZP.AdapterNeodosielaSpravu = True

            elif q_get == 'pripravOdosielanie':
                assistant.pripravOdosielanie()

            elif q_get == 'pripravTelefonovanie':
                assistant.pripravTelefonovanie()

            elif q_get == 'vypniInternet':
                #nie je treba sa ani pytat, proste to skus
                worker.vypniInternet()

            elif q_get == 'pwrKeyAdapter':
                worker.pwrKeyAdapter()
                worker.pripojAdapter()

        except:
            pocet_pokusov -= 1
            if pocet_pokusov == 0:
                log.exception(
                    "AdapterManager zlyhal vela krat, restartujem ho!")
                ZP.adapterJob_prioDeq.put(
                    'pwrKeyAdapter', delete=False
                )  #keep other jobs pending as we are just fixing something
                pocet_pokusov = 3
            else:
                log.exception("Adapter zlyhal, restartujem po dalsich " +
                              str(pocet_pokusov) + " zlyhaniach.")
Example #8
0
def main():
    try:

        log.debug("RPI STARTED!")
        loop_count = 0  #just informative
        pociatokSpanku = 0  #used for calculating sleeping periode
        cas_celkoveho_behu = 0  #time of the whole run counter
        '''load main konfiguration dictionary ZP.konfigD for the current run
			konfig.json file contains:
			- settings written at the end of previous run (<= we are in relaxing mode)
			- default settings due to user explicit request to shut down the machine. 
			Or if crash of this program happens during running process - this is why we keep
			konfig.json on default values during running of this program. See overwriting of this file few lines bellow...
		'''
        ZP.konfigD = vseobecne.Pomoc.precitajJsonFile(ZP.MAIN_DIR +
                                                      "konfig.json")
        #load main counter dictionary odpocetD that keeps current value of counter for each interval (if counter is == 0, activity is run). Counter is decresead be ZP.FREQ value after each main loop
        odpocetD = vseobecne.Pomoc.precitajJsonFile(ZP.MAIN_DIR +
                                                    "odpocet.json")
        #rewrite odpocet.json to default value just in case program crashes - it will restart with default values.
        specialne.zapisDefaultnyOdpocet()
        '''since we just started the program. Add some pre-load time to every interval-counter value. This makes sure we run mesuring of temperature or gps beforehand
		so that we have some values to work when counter == 0. This is because the sensors' controls are starting at counter == 0 and they need some current temperatures mesurements to work with.
		It also secures the cases when gps/temp mesuring is not started at the same time'''
        for prem in ZP.INTERVALOVE_PREMENNE:  #for synchronisation purpose we are assigning ZP.LOADING_CAS to each of 4 interval-counters
            if odpocetD[
                    prem] != None:  #interval-counter == None means this activity is to be ignored (requested by user)
                odpocetD[prem] = odpocetD[prem] + ZP.LOADING_CAS

        #rewrite konfig.json to default value in case program crashes. It will then restart with default configuration.
        specialne.zapisDefaultnyKonfig()
        """Create troubleMonitor object to monitor all troubles in one place and manage runLevels through it."""
        ZP.troubleMonitor = pomocneObj.TroubleMonitor()
        """Create logger for one run per line logging."""
        ZP.logPerRun = pomocneObj.LogPerRun(
        )  #prefill with these specific names or dummy (None) value. Otherwise they would be ignored <- see 'run' variable in pomocneObj.LogPerRun
        for i in range(ZP.POCET_SENZOROV):
            with ZP.logPerRun_lock:
                ZP.logPerRun.addItem(
                    itemName=str(ZP.SENZORY[i]),
                    itemValue=None,
                    itemPosition=i + 150,
                    specialType='osilacie_a_zaseknutia'
                )  #to have the header of all controls in the log even if some won't run
                ZP.logPerRun.addItem(
                    itemName=
                    "((ZP.rozptylTep, ZP.rozptylVlh), ZP.VELKOST_OKNA_MERANI, ZP.MINIMALNA_TOLEROVANA_KVALITA)",
                    itemValue=str(((ZP.rozptylTep,
                                    ZP.rozptylVlh), ZP.VELKOST_OKNA_MERANI,
                                   ZP.MINIMALNA_TOLEROVANA_KVALITA)),
                    itemPosition=250,
                    specialType=None
                )  #just one log of current constants setup: ZP.rozptylTep, ZP.rozptylVlh
                ZP.logPerRun.addItem(
                    itemName=str(ZP.SENZORY[i]),
                    itemValue=None,
                    itemPosition=i + 170,
                    specialType='filter'
                )  #to have the header of all controls in the log even if some won't run

        #THREADS:
        '''create and start thread (running in the background) that manages GPRS adapter work over serial port
			It is necessary that there is only one access to serial port at a time because of the serial port nature. Therefore we can assign any work for the adapter
			through the following thread (specifically through it's custom made queue defined here: pomocneObj.PrioDeque). This queue has defined priorities and special order of specific activities.
			AdapterManager is working on them based on this given order. 
		'''
        adapterManager_thread = threading.Thread(target=adapterManager.praca,
                                                 name='AdapterManager',
                                                 daemon=True)
        adapterManager_thread.start()

        #adapter is booted together with RPI (unconvenient GPIOs setup at boot that is difficult to modify) but it doesnt work well so it's better to restart it.
        #so shut it down:
        sysfun.pin_to_HighState(
        )  #first put it to high state (necessary, otherwise adapter doesn't work properly)
        ZP.adapterJob_prioDeq.put(
            'pwrKeyAdapter',
            delete=False)  #first shutdown/startup is necessary in all cases
        #pripojAdapter work is already included in pwrKeyAdapter work
        #adapter jobs are running in the background so just give adapter some time to restart
        log.debug(
            "Giving adapter some time to start/shutdown before proceeding...")
        time.sleep(12)
        if not adapterWorker.otazkaOdpoveda(
        ):  #at this time we are checking if adapter was started or shut down. in latter case, turn it back on
            log.debug("Adapter je zrejme vypnuty. Startujem...")
            #it's now turned OFF so start it again:
            ZP.adapterJob_prioDeq.put('pwrKeyAdapter', delete=False)
            # time.sleep(4) - we cannot put sleep here because it would change starting time if there was problem with adapter
        else:
            time.sleep(
                1.9
            )  #if it's replying, hw.Adapter.otazkaOdpoveda will return faster than if it's not. so wait for about otazkaOdpoveda timeout time

        #start AlarmCheck thread that is assigning 'telefonuj' work to AdapterManager in case alarm is on
        alarmCheckThread = threading.Thread(
            target=specialne.initiatePhoneCallOnAlarm,
            name='AlarmCheck',
            daemon=True)
        alarmCheckThread.start()

        #for each of the sensors, create one sensor-check thread that is checking it's proper functionality and heat index healthy range:
        for snz in ZP.SENZORY[:6]:
            meno = 'kontrolaThread' + snz
            kntrl = threading.Thread(target=kontrola.run,
                                     args=(snz, ),
                                     name=meno,
                                     daemon=True)
            kntrl.start()
        sysfun.clearStartupTime()

        ###	MAIN LOOP:
        #this is the core code. It runs every ZP.FREQ seconds (6 seconds) from the start of RPI until shutdown is called.
        while True:
            log.info("BEH CISLO: " + str(loop_count))
            start_cas = time.time()

            #1. #############################
            #  		MESSAGE RECEIVED?					#
            #																#
            #check if new message was received, if so, load requested configuration:
            with ZP.prijataSprava_dequelock:
                if len(
                        ZP.prijataSprava_deque
                ) == 1:  #this is only == 1 if adapterManager filled it prijataSprava_deque with a newly received message
                    log.debug("Nacitavam novy konfigD (lebo prisla sprava).")
                    with ZP.konfigD_lock:
                        (
                            prijataSprava, ZP.konfigD
                        ) = ZP.prijataSprava_deque.pop(
                        )  #left side of this assignment is what this deque normally contains
                    #reset interval-counters for simplicity. Mainly to keep intervals synchronized in case one of them is to be modified by the message.
                    log.debug("Resetujem odpocetD (lebo prisla sprava).")
                    odpocetD = specialne.resetujOdpocetD(ZP.konfigD, ZP.FREQ)
                    '''reset all sensor-checks mainly to avoid controling some old state that the user is no longer interested in.
					(Run them with empty lists and set all semaphores True):
					'''
                    log.debug("Resetujem kontroly (lebo prisla sprava).")
                    ZP.resetujKontroly = True
                    for q in ZP.Q:
                        q.put(1)
                        q.join()
                    #all sensor-checks were just run "unloaded".
                    ZP.resetujKontroly = False
                    '''Negate information about sensors' issues because the user just requested to turn off the alarm:
					In case there are still problems with sensors, they will be rediscovered on freshly started sensor-checks which are triggered by just received message.'''
                    if not ZP.troubleMonitor.isOn_mainAlarm(
                    ):  #reset the information about troubles to all ok
                        ZP.nezdraveTep_senzory = "00000000"
                        ZP.oscilujuceTep_senzory = "00000000"
                        ZP.zaseknute_senzory = "00000000"
            ################################

            #2. ###########################
            # 				TROUBLES?						#
            #															#
            #Check if you there are some troubles and if necessary, modify the running intervals.
            #1. main alarm is ON => configD will be modified to default intervals no matter what user has requested.
            if (ZP.troubleMonitor.isOn_mainAlarm()):
                log.debug(
                    "Alarm je zapnuty, prepisujem konfiguraciu (konfiD) na neustaly rezim."
                )
                with ZP.konfigD_lock:
                    for i in ZP.troubleMonitor.mainAlarm_konfigD:
                        ZP.konfigD[i] = ZP.troubleMonitor.mainAlarm_konfigD[
                            i]  #modify running intervals to restless mode
                    for i in ZP.troubleMonitor.mainAlarm_konfigD:
                        #reset odpocetD in case it is not aware of new configuration. This condition is true at most one time after alarm was started
                        #further times, this condition will always be false because interval-counters will never get bigger than konfigD corresponding values
                        if odpocetD[i] == None or odpocetD[i] > ZP.konfigD[i]:
                            odpocetD = specialne.resetujOdpocetD(ZP.konfigD, 0)
            ###############################

            #3. ###########################
            # 				INFORMING						#
            #															#
            #when the time comes, perform informing ( = receive instructions if any AND send current configuration and results). This work is assigned to AdapterManager.
            if odpocetD["intervalInfTep"] == 0 or odpocetD[
                    "intervalInfGps"] == 0:
                ZP.adapterJob_prioDeq.put('posta')
            ################################

            ###############################
            #			some side tasks		 			#
            #															#
            #ZP.adapterJob_prioDeq.put('pripravTelefonovanie') #no longer necessary

            #make adapter ready in advance for communication with the server (ZP.PREDPRIPRAVA_ODOSIELANIA seconds ahead)
            #(this code isn't crucial for proper functionality, it's only convenient to prepare the adapter beforehand):
            specialne.zapniInternetVopred(odpocetD['intervalInfTep'],
                                          odpocetD['intervalInfGps'])

            #inicializations for logging:
            ZP.DEBUG = {
                'snz1': {},
                'snz2': {},
                'snz3': {},
                'snz4': {},
                'snz5': {},
                'snz6': {},
                'snz7': {},
                'snz8': {}
            }
            ZP.filterVysledkyD = {'snz1': (), 'snz2': (), 'snz3': (), 'snz4': (), 'snz5': (), \
            'snz6': (), 'vonkajsi':  (('-','-'), '-', '-'), 'rpi':  (('-','-'), '-', '-'), 'wittyPi':  (('-','-'), '-', '-')}
            #logging "per line" of current sensors with issues:
            ZP.logPerRun.addItem('nezdraveTep_senzory', ZP.nezdraveTep_senzory,
                                 200)
            ZP.logPerRun.addItem('oscilujuceTep_senzory',
                                 ZP.oscilujuceTep_senzory, 201)
            ZP.logPerRun.addItem('zaseknute_senzory', ZP.zaseknute_senzory,
                                 202)
            #logging of current konfigD and odpocetD:
            log.info("		{}	{}	{}	{}	{}	{}	{}		{}".format(
                'mT', 'mG', 'iT', 'iG', 'tLow', 'tHigh', 'onOff', 'aktBoxy'))
            znenie = ''
            for i in ZP.VOLBY_ANDROID:
                hodnota = str(ZP.konfigD[i])
                if hodnota == "123456789":
                    znenie += '\t' + "off"
                else:
                    znenie += '\t' + str(ZP.konfigD[i])
            log.info("konfigD: " + znenie)
            znenie = ''
            for i in ZP.INTERVALOVE_PREMENNE:
                znenie += '\t' + str(odpocetD[i])
            log.info("odpocetD: " + znenie)
            ##############################

            #4. #########################
            #					MESURING					#
            #Run temperature mesuring ahead of time (ZP.LOADING_CAS) if measuring is required or if sensor-checks didn't yet confirm all checks ok
            onSenzory = ZP.SENZORY[:
                                   9]  #just FYI that we are mesuring all sensors every time.
            if odpocetD[
                    'intervalMerTep'] != None:  #since GPS mesuring is not yet available, this is always True
                if (odpocetD['intervalMerTep'] <= ZP.LOADING_CAS
                        or not all(ZP.Kntrl_tep_succesfully_finished)
                    ):  #meraj uz v predstihu resp. pri kontrole
                    tepMer_thread = threading.Thread(
                        target=meranie.TemperatureHumidity.ofSensors,
                        name="MerajTep",
                        args=(onSenzory, ),
                        daemon=False)
                    tepMer_thread.start()

            #IGNORED. GPS feature is not fully implemented yet
            meranieGpsJePozadovane = False
            # meranieGpsJePozadovane = True if odpocetD['intervalMerGps'] != None else False
            if meranieGpsJePozadovane:
                if odpocetD[
                        'intervalMerGps'] <= ZP.LOADING_CAS or not ZP.Kntrl_gps_OK:  #meraj uz v predstihu resp. pri kontrole
                    if False:
                        startGps_thread = threading.Thread(
                            target=mka.Gps.startuj_GPS, name="StartGps")
                        gpsMer_thread = threading.Thread(
                            target=mka.Gps.meraj_GPS, name="MerajGps")
                        #spustanie gps pocas behu:
                        if event_gpsNastartovane.is_set():
                            gpsMer_thread.start()
                        else:
                            startGps_thread.start()
                            print("startGPS started")
                #should be moved few lines bellow
                if 'MerajGps' in active_threads:
                    gpsMer_thread.join()

            #Temperature mesuring. Lasts maximum 5.1 seconds. In case it's not yet finished, wait for it to finish.
            active_threads = [x.name for x in threading.enumerate()]
            if 'MerajTep' in active_threads:
                tepMer_thread.join()
                casMerania = time.time() - ZP.merTepCas_debug
                if casMerania > 5.9:
                    log.warning(
                        "Meranie teploty prebehlo nezvycajne pomaly, trvalo:" +
                        str(casMerania))
                ZP.merTepCas_debug = 0
            #############################

            #5. #########################
            #			SENSORS-CHECKS				#
            #														#
            #first clear all checks' events to not check sensors that are not active (empty cages).
            for e in ZP.kntrlEventy:
                e.clear()
            #started exactly on mesuring intervals counter == 0 (odpocetD[intervalMerTep])
            if odpocetD['intervalMerTep'] == 0:
                #INITIATE CHECKS - only for non-empty cages (konfigD[aktBoxy])
                for ix in range(ZP.POCET_SENZOROV):
                    if ZP.konfigD['aktBoxy'][ix] == '1':
                        ZP.kntrlEventy[ix].set()
                    else:
                        #this is just for logging:
                        ZP.filterVysledkyD[ZP.SENZORY[ix]] = (('-', '-'), '-',
                                                              '-')
            #CONTINUE with running checks until they all confirm their check value True
            if odpocetD['intervalMerTep'] == 0 or not all(
                    ZP.Kntrl_tep_succesfully_finished):
                for ix in range(ZP.POCET_SENZOROV):
                    if ZP.konfigD['aktBoxy'][ix] == '1':
                        ZP.Q[ix].put(1)
            for q in ZP.Q:
                q.join()

            #6. ###################################
            #			WRITE-OFF INTERVAL-COUNTERS			#
            #																			#
            #work has been performed, write-off the counter for each activity
            #work to be performed on the next run will have it's counter == 0
            for inter in ZP.INTERVALOVE_PREMENNE:
                if odpocetD[inter] != None:
                    if odpocetD[inter] == 0:
                        odpocetD[inter] = ZP.konfigD[inter] - ZP.FREQ
                    else:
                        odpocetD[inter] -= ZP.FREQ
                if ZP.konfigD[inter] == 123456789:
                    odpocetD[inter] = None
            #######################################

            ###############################
            #			some side tasks		 			#
            #															#
            log.debug("Tabulka kontrol:")
            i = 0
            for senz in ZP.SENZORY[:6]:
                znenie = ''
                for k in ZP.DEBUG[senz]:
                    znenie += str(ZP.DEBUG[senz][k]) + "\t"
                log.debug(znenie)

            # log.debug("kontorly:" + str(ZP.Kntrl_tep_succesfully_finished))
            log.debug("adapterManagerQ:" + str(ZP.adapterJob_prioDeq.deqList))
            ZP.logPerRun.printHlavicku()
            ZP.logPerRun.print()
            ###############################

            #7. ###################################
            #			SHUTDOWN / SLEEP / CONTINUE			#
            #																			#
            #check if there is a need to shutdown RPI (sleep or shutdown forever)
            #1. specialny pripad - restaruj RPI ak adapter neodpoveda na restarty:
            if (ZP.troubleMonitor.adapterNotRestarting_tryAgain == False):
                vseobecne.Pomoc.prepisJsonFile(ZP.konfigD,
                                               ZP.MAIN_DIR + "konfig.json")
                #resetuj odpocet.json na nuly aby sa vsetko spustilo pri zapnuti RPI
                for i in ZP.INTERVALOVE_PREMENNE:
                    odpocetD[i] = 0 if odpocetD[i] != None else None
                vseobecne.Pomoc.prepisJsonFile(odpocetD, "odpocet.json")
                log.warning(
                    "Restartujem RPI kvoli problemu s restartovanim adaptera!")
                sysfun.uspiRpi(ZP.TRVANIE_RESTARTU,
                               datetime.now())  # THIS LINE ENDS THE!

            #if above didn't end the program, then we continue here:
            #check if there are any intervals in ZP.konfigD different than None
            nieNoneOdpocty = [x for x in odpocetD.values() if x != None]
            #if all intervals in ZP.konfigD == None (nieNoneOdpocty is [])
            if nieNoneOdpocty == []:  #then it's signal to shutdown RPI forever:
                oddych = None  #this value is used at the bottom (outside of Main loop)
                specialne.zapisDefaultnyOdpocet()  #for fresh RPI start
                specialne.zapisDefaultnyKonfig()  #for fresh RPI start
                log.info("Dostal som instrukcie na vypnutie RPI.")
                break  #breaks the main loop, jumps at the bottom to shut down RPI
            else:  #else, check if there is a need to sleep
                pozadovany_oddych = min(
                    nieNoneOdpocty
                )  #the minimum interval-counter is the maximum possible "sleep" time of RPI
                cas_do_konca_behu = ZP.FREQ - (time.time() - start_cas)
                korekcia = 0  #correction to make the sleep time fit perfectly. 0 means no correction needed
                #oddych sa vyratava zlozitejsou formulkou ale plati, ze cas do konca behu nie je podstatny pretoze sa prekryva s SOME_TIME_TO_FINISH_ADA.JOBS
                #sysfun.uspiRpi() rata spanok od "pociatokSpanku" po dobu "oddych"
                oddych = round(pozadovany_oddych + cas_do_konca_behu -
                               ZP.RPI_BOOTUP_CAS - ZP.LOADING_CAS + korekcia)
                log.debug("Vyratany oddych (min Odpocet):" +
                          str(pozadovany_oddych) + ", Skutocny mozny oddych:" +
                          str(oddych))

                #now check that new message wasn't received around this moment
                #we dont' want to ignore that new message so don't proceed with shutdown if received
                if len(ZP.prijataSprava_deque) == 0:
                    #also check other stuff before shutting down:
                    if (oddych > ZP.MIN_ODDYCH
                            and not ZP.troubleMonitor.isOn_mainAlarm()
                            and all(ZP.Kntrl_tep_succesfully_finished)
                            and ZP.AdapterNeodosielaSpravu
                            and specialne.MessageNotInAdapterQueue()):
                        log.info("Uspavam RPI.")
                        log.debug(
                            "Uspavam RPI pretoze 1. oddych > 90 sekund, 2.nie je zapnuty alarm, 3. nebezi ziadna kontrola, 4. AdapterNeodosielaSpravu a 5. sprava nie je v adapterQueue: "
                        )
                        #store current configuration in a file for it to be used for next run
                        vseobecne.Pomoc.prepisJsonFile(
                            ZP.konfigD, ZP.MAIN_DIR + "konfig.json")
                        #since we are putting RPI to sleep, we need to write-off interval-counters by the lenght of the sleep so that they are ready for the new run
                        for i in ZP.INTERVALOVE_PREMENNE:
                            odpocetD[i] = odpocetD[
                                i] - pozadovany_oddych if odpocetD[
                                    i] != None else None
                        vseobecne.Pomoc.prepisJsonFile(odpocetD,
                                                       "odpocet.json")
                        pociatokSpanku = datetime.now()
                        break  #breaks the main loop, jumps at the bottom to shut down RPI
            #######################################

            #8. ###################################
            #			CONTINUE WITH THE MAIN LOOP			#
            #																			#
            loop_count += 1
            #assure the run is no shorter than 6 seconds, then repeat the Main loop:
            end_cas = time.time()
            cas_behu = end_cas - start_cas
            if cas_behu < ZP.FREQ:
                cakaj = ZP.FREQ - cas_behu
            else:
                cakaj = 0
                log.warning("Beh prebehol prilis pomaly, trval" +
                            str(cas_behu) + "sekund!")
            cas_celkoveho_behu += (cas_behu + cakaj)
            log.info("Cas celkoveho behu: " + str(cas_celkoveho_behu) +
                     " sekund.")
            log.info("")
            time.sleep(cakaj)
            #######################################

        ###################################
        #		 WE ARE SHUTTING DOWN 				#
        #																	#
        """We will get here only if "all runs" of Main loop were succesfully finished (RPI wasn't physically shut down):"""
        #there is no more "posta" jobs in adapter queue so we can shut down the adapter:
        ZP.adapterJob_prioDeq.put(
            'pwrKeyAdapter',
            delete=False)  #shut down adapter functionality gracefully
        """adapter might have some jobs to do and we are already shuting the device down - but there are only 2 crucial jobs that might be of concern:
		1. phone calling in alarm situation - this wont happen because we wouldnt ask for Rpi shutdown in case of alarm
		2. message sending - if we got to this line it means that either there is no need for informing in this DAY or ... 
		 in any case we give adapter SOME_TIME_TO_FINISH_ADAPTER_JOBS anyway."""
        log.info("Giving adapterManager some time to finish assigned jobs: " +
                 str(ZP.SOME_TIME_TO_FINISH_ADAPTER_JOBS) + " seconds")
        time.sleep(ZP.SOME_TIME_TO_FINISH_ADAPTER_JOBS)
        sysfun.uspiRpi(oddych,
                       pociatokSpanku)  #program is shut down by this function
        ###################################

    except:
        log.exception("EXCEPTION!")
        sys.exit()