Esempio n. 1
0
def run():
    try:
        log.info('micropython p1 meter is starting...')
        fb.clear()
        asyncio.run(main(glb_mqtt_client))
    finally:
        # status
        fb.clear(fb.RED)

        log.info("Clear async loop retained state")
        asyncio.new_event_loop()  # Clear retained state

        reboot(10)
Esempio n. 2
0
 def connect(self):
     global _conn_errors
     if self.mqtt_client is None:
         log.info("create mqtt client {0}".format(self.server))
         self.mqtt_client = MQTTClient(NETWORK_ID,
                                       self.server,
                                       port=self.port,
                                       user=self.user,
                                       password=self.password)
     if wlan.status() == network.STAT_GOT_IP:
         try:
             print("connecting to mqtt server {0}".format(self.server))
             self.mqtt_client.connect()
             print("Connected")
         except (MQTTException, OSError) as e:
             # try to give a decent error for common problems
             if type(e) is type(MQTTException()):
                 if e.args[0] == 5:  # EIO
                     log.error("MQTT server error {}: {}".format(
                         e, "check username/password"))
                 elif e.args[0] == 2:  # ENOENT
                     log.error("MQTT server error {}: {}".format(
                         e, "server address or network"))
                 else:
                     log.error("{} {}".format(type(e).__name__, e))
             else:
                 ## OSError
                 if int(e.args[0]) == -2:  # could not resolve ?
                     log.error("OS Error {}: {}".format(
                         e,
                         "Host unreachable, is mDNS working to resolve MQTT server name ?"
                     ))
                 elif e.args[0] in (113, 23):  # EHOSTUNREACH
                     log.error("OS Error {}: {}".format(
                         e,
                         "Host unreachable, check server address or network"
                     ))
                 elif e.args[0] < 0:  # some negative socket error
                     _conn_errors = +1
                     if _conn_errors > 10:
                         log.error("OS Error {}: {}".format(
                             e, "attempting reboot to fix"))
                         reboot()
                     else:
                         log.error("OS Error {}".format(e))
                 else:
                     log.error("{} {}".format(type(e).__name__, e))
     else:
         log.warning('network not ready/stable')
def measure(q, offline, debug, ts_channels, ts_server_url, filtered_temperature, ds18b20Sensors, bme680Sensors, bme680Inits, dhtSensors, aht10Sensors, sht31Sensors, hdc1008Sensors, bh1750Sensors, tcSensors, bme280Sensors, pcf8591Sensors, ee895Sensors, weightSensors, hxInits, connectionErrors, measurementIsRunning):
    measurementIsRunning.value = 1 # set flag
    ts_fields = {}
    try:
        ts_fields, bme680Inits = measure_all_sensors(debug, filtered_temperature, ds18b20Sensors, bme680Sensors, bme680Inits, dhtSensors, aht10Sensors, sht31Sensors, hdc1008Sensors, bh1750Sensors, tcSensors, bme280Sensors, pcf8591Sensors, ee895Sensors, weightSensors, hxInits)
        if len(ts_fields) > 0:
            ts_datetime=thingspeak_datetime()
            if offline == 1 or offline == 3:
                try:
                    s = write_csv(ts_fields, ts_channels, ts_datetime)
                    if s and debug:
                        logger.info("Data succesfully saved to CSV-File.")
                except Exception as ex:
                    logger.exception("Exception in measure / write_csv")

            # if transfer to thingspeak is set
            if (offline == 0 or offline == 1 or offline == 2) and ts_channels:
                # update ThingSpeak / transfer values
                connectionErrorHappened = manage_transfer_to_ts(ts_channels, ts_fields, ts_server_url, offline, debug, ts_datetime)

                if connectionErrorHappened:
                    MAX_RETRIES_IN_A_ROW = 3
                    # Do Rebooting if to many connectionErrors in a row
                    connectionErrors.value +=1
                    logger.error("Failed internet connection. Count: " + str(connectionErrors.value) + "/" + str(MAX_RETRIES_IN_A_ROW))
                    if connectionErrors.value >= MAX_RETRIES_IN_A_ROW:
                        if not debug:
                            logger.critical("Too many Connection Errors in a row => Rebooting Raspberry")
                            time.sleep(4)
                            reboot()
                        else:
                            logger.critical("Too many Connection Errors in a row but did not reboot because console debug mode is enabled.")
                else:
                    if connectionErrors.value > 0:
                        if debug:
                            logger.warning("Connection Errors (" + str(connectionErrors.value) + ") Counting resetet because transfer succeded.")
                        # reset connectionErrors because transfer succeded
                        connectionErrors.value = 0

        elif debug:
            logger.info("No measurement data to send.")

    except Exception as ex:
        logger.exception("Exception during measure (outer).")
    measurementIsRunning.value = 0 # clear flag
Esempio n. 4
0
def start_measurement(measurement_stop):
    try:
        global burn_in_time
        start_time = time.time()

        # load settings
        settings = get_settings()
        ts_channels = settings[
            "ts_channels"]  # ThingSpeak data (ts_channel_id, ts_write_key)
        ts_server_url = settings["ts_server_url"]
        debuglevel = settings["debuglevel"]
        if debuglevel <= 10:
            debug = True  # flag to enable debug mode (HDMI output enabled and no rebooting)
        else:
            debug = False  # flag to enable debug mode (HDMI output enabled and no rebooting)

        wittyPi = settings["wittyPi"]
        offline = settings["offline"]  # flag to enable offline csv storage

        isLowVoltage = getStateFromStorage('isLowVoltage', False)
        if isLowVoltage == True:
            interval = wittyPi["low"]["interval"]
            shutdownAfterTransfer = wittyPi["low"]["shutdownAfterTransfer"]
        else:
            interval = wittyPi["normal"]["interval"]
            shutdownAfterTransfer = wittyPi["normal"]["shutdownAfterTransfer"]

        if debug:
            logger.info("The measurements have started.")

        # with process shared variables
        connectionErrors = Value('i', 0)
        measurementIsRunning = Value('i', 0)

        if interval and not isinstance(interval, int) or interval == 0:
            interval = 0
            logger.info("Stop measurement because interval is null.")
            measurement_stop.set()

        # read configured sensors from settings.json
        ds18b20Sensors = get_sensors(settings, 0)
        bme680Sensors = get_sensors(settings, 1)
        weightSensors = get_sensors(settings, 2)
        dhtSensors = get_sensors(settings, 3)
        tcSensors = get_sensors(settings, 4)
        bme280Sensors = get_sensors(settings, 5)
        pcf8591Sensors = get_sensors(settings, 6)
        ee895Sensors = get_sensors(settings, 7)
        aht10Sensors = get_sensors(settings, 8)
        sht31Sensors = get_sensors(settings, 9)
        hdc1008Sensors = get_sensors(settings, 10)
        bme680Inits = []

        # -- Run Pre Configuration --
        # if bme680 is configured
        for (sensorIndex, bme680Sensor) in enumerate(bme680Sensors):
            bme680Init = {}
            if 'burn_in_time' in bme680Sensor:
                burn_in_time = bme680Sensor["burn_in_time"]
            sensor = initBME680FromMain(bme680Sensor)
            gas_baseline = burn_in_bme680(sensor, burn_in_time)
            bme680Init['sensor'] = sensor
            bme680Init['gas_baseline'] = gas_baseline
            bme680Inits.append(bme680Init)

        # if hx711 is set
        hxInits = []
        for (i, sensor) in enumerate(weightSensors):
            _hx = init_hx711(sensor)
            hxInits.append(_hx)

        # PCF8591
        if pcf8591Sensors and len(pcf8591Sensors) == 1:
            voltage = get_raw_voltage(
                pcf8591Sensors[0]
            )  # initial measurement as first measurement is always wrong

        # -- End Pre Configuration --

        # start at -6 because we want to get 6 values before we can filter some out
        counter = -6
        time_measured = 0
        time_measured_Voltage = 0

        # Main loop which checks every second
        while not measurement_stop.is_set():
            counter += 1
            time_now = time.time()

            for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
                checkIfSensorExistsInArray(sensorIndex)
                if 'device_id' in sensor:
                    read_unfiltered_temperatur_values(sensorIndex, sensor)

            time_measured_Voltage, interval, shutdownAfterTransfer, isLowVoltage = check_wittypi_voltage(
                time_measured_Voltage, wittyPi, pcf8591Sensors, isLowVoltage,
                interval, shutdownAfterTransfer)

            # wait seconds of interval before next check
            # free ThingSpeak account has an upload limit of 15 seconds
            isTimeToMeasure = ((time_now - time_measured >= interval) or
                               (interval == 1)) and counter > 0
            if isTimeToMeasure:
                now = time.strftime("%H:%M", time.localtime(time_now))
                lastMeasurement = time.strftime("%H:%M",
                                                time.localtime(time_measured))
                if time_measured == 0:
                    print("First time measurement. Now: " + str(now))
                else:
                    print("Last measurement was at " + str(lastMeasurement))
                    print("Time over for a new measurement. Time is now: " +
                          str(now))
                time_measured = time.time()

                check_undervoltage('0x7')

                if measurementIsRunning.value == 0:
                    q = Queue()
                    p = Process(target=measure,
                                args=(q, offline, debug, ts_channels,
                                      ts_server_url, filtered_temperature,
                                      ds18b20Sensors, bme680Sensors,
                                      bme680Inits, dhtSensors, aht10Sensors,
                                      sht31Sensors, hdc1008Sensors, tcSensors,
                                      bme280Sensors, pcf8591Sensors,
                                      ee895Sensors, weightSensors, hxInits,
                                      connectionErrors, measurementIsRunning))
                    p.start()
                    p.join()

                else:
                    logger.warning(
                        "Forerun measurement is not finished yet. Consider increasing interval."
                    )

                # stop measurements after uploading once
                if interval == 1:
                    print("Only one measurement was set => stop measurements.")
                    measurement_stop.set()

                    if shutdownAfterTransfer:
                        isMaintenanceActive = getStateFromStorage(
                            'isMaintenanceActive', False)
                        print("Wert isMaintenanceActive: " +
                              str(isMaintenanceActive))
                        while isMaintenanceActive:
                            isMaintenanceActive = getStateFromStorage(
                                'isMaintenanceActive', False)
                            print(
                                "Shutting down was set but Maintenance mode is active, delaying shutdown!"
                            )
                            print("Wert isMaintenanceActive: " +
                                  str(isMaintenanceActive))
                            time.sleep(10)
                        print(
                            "Shutting down was set => Waiting 10seconds and then shutdown."
                        )
                        tblink = threading.Thread(target=blink_led,
                                                  args=(settings["led_pin"],
                                                        0.25))
                        tblink.start()
                        time.sleep(10)
                        shutdown()

            time.sleep(6)  # wait 6 seconds before next measurement check

        end_time = time.time()
        time_taken = end_time - start_time  # time_taken is in seconds
        time_taken_s = float(
            "{0:.2f}".format(time_taken))  # remove microseconds
        print("Measurement-Script runtime was " + str(time_taken_s) +
              " seconds.")

    except Exception as ex:
        logger.exception("Unhandled Exception in start_measurement")
        if not debug:
            time.sleep(10)
            reboot()
Esempio n. 5
0
def main():
    try:
        global isActive, measurement_stop, measurement, debug, GPIO_BTN, GPIO_LED
        logger = logging.getLogger('HoneyPi')
        logger.setLevel(logging.DEBUG)
        fh = logging.FileHandler(logfile)
        fh.setLevel(logging.DEBUG)
        # create console handler with a higher log level
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)
        # create formatter and add it to the handlers
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
        # add the handlers to the logger
        logger.addHandler(fh)
        logger.addHandler(ch)
        #logging.basicConfig(filename=logfile, format='%(asctime)s %(levelname)-8s %(message)s', level=logging.INFO)
        #logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
        logger.info('HoneyPi Started')

        # Zaehlweise der GPIO-PINS auf der Platine
        GPIO.setmode(GPIO.BCM)

        # read settings for number of GPIO pin
        settings = get_settings()
        debuglevel = settings["debuglevel"]

        print("Debuglevel: " + str(debuglevel))
        time.sleep(5)
        if debuglevel <= 10:
            debug = True  # flag to enable debug mode (HDMI output enabled and no rebooting)
        else:
            debug = False  # flag to enable debug mode (HDMI output enabled and no rebooting)
        GPIO_BTN = settings["button_pin"]
        GPIO_LED = settings["led_pin"]

        # setup LED as output
        GPIO.setup(GPIO_LED, GPIO.OUT)

        # blink with LED on startup
        tblink = threading.Thread(target=blink_led, args=(GPIO_LED, ))
        tblink.start()

        # after start is AccessPoint down
        stop_ap()

        # Create virtual uap0 for WLAN
        create_ap()

        # Call wvdial for surfsticks
        start_wvdial()

        if not debuglevel <= 20:
            # stop HDMI power (save energy)
            print("Info: Shutting down HDMI to save energy.")
            stop_tv()
            stop_hdd_led()
        else:
            logger.info("Info: Raspberry Pi has been powered on.")
            start_hdd_led()

        logger.info("Default gateway used for Internet connection is: " +
                    str(get_default_gateway_linux()))
        logger.info("Interface eth0 is up: " +
                    str(get_interface_upstatus_linux('eth0')))
        logger.info("Interface wlan0 is up: " +
                    str(get_interface_upstatus_linux('wlan0')))

        # start as seperate background thread
        # because Taster pressing was not recognised
        isMaintenanceActive = setStateToStorage('isMaintenanceActive', False)
        measurement_stop = threading.Event(
        )  # create event to stop measurement
        measurement = threading.Thread(target=start_measurement,
                                       args=(measurement_stop, ))
        measurement.start()  # start measurement

        # setup Button
        GPIO.setup(
            GPIO_BTN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN
        )  # Set pin 16 to be an input pin and set initial value to be pulled low (off)
        #GPIO.setup(GPIO_LED, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Set LED to be an input pin and set initial value to be pulled low (off)
        bouncetime = 100  # ignoring further edges for 100ms for switch bounce handling
        # register button press event
        GPIO.add_event_detect(GPIO_BTN,
                              GPIO.BOTH,
                              callback=button_pressed,
                              bouncetime=bouncetime)
        #GPIO.add_event_detect(GPIO_LED, GPIO.BOTH, callback=get_led_state)

        # Main Lopp: Cancel with STRG+C
        while True:
            time.sleep(
                0.2)  # wait 200 ms to give CPU chance to do other things
            pass

        print("This text will never be printed.")
    except Exception as e:
        logger.critical("Unhandled Exception in main " + repr(e))
        if not debug:
            time.sleep(60)
            reboot()
Esempio n. 6
0
                              callback=button_pressed,
                              bouncetime=bouncetime)
        #GPIO.add_event_detect(GPIO_LED, GPIO.BOTH, callback=get_led_state)

        # Main Lopp: Cancel with STRG+C
        while True:
            time.sleep(
                0.2)  # wait 200 ms to give CPU chance to do other things
            pass

        print("This text will never be printed.")
    except Exception as e:
        logger.critical("Unhandled Exception in main " + repr(e))
        if not debug:
            time.sleep(60)
            reboot()


if __name__ == '__main__':
    try:
        main()

    except (KeyboardInterrupt, SystemExit):
        close_script()

    except Exception as e:
        logger.error("Unhandled Exception in __main__ " + repr(e))
        if not debug:
            time.sleep(60)
            reboot()
Esempio n. 7
0
def main():
    try:
        global isActive, measurement_stop, measurement, debug, GPIO_BTN, GPIO_LED

        # Zaehlweise der GPIO-PINS auf der Platine
        GPIO.setmode(GPIO.BCM)

        # read settings for number of GPIO pin
        settings = get_settings()
        debuglevel = int(settings["debuglevel"])
        debuglevel_logfile = int(settings["debuglevel_logfile"])

        logger = logging.getLogger('HoneyPi')
        logger.setLevel(logging.DEBUG)
        fh = RotatingFileHandler(logfile,
                                 maxBytes=5 * 1024 * 1024,
                                 backupCount=365)
        fh.setLevel(logging.getLevelName(debuglevel_logfile))
        # create console handler with a higher log level
        ch = logging.StreamHandler()
        ch.setLevel(logging.getLevelName(debuglevel))
        # create formatter and add it to the handlers
        formatter = logging.Formatter(
            '%(asctime)s | %(levelname)s | %(name)s | %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
        # add the handlers to the logger
        logger.addHandler(fh)
        logger.addHandler(ch)

        time.sleep(1)

        if debuglevel <= 10:
            debug = True  # flag to enable debug mode (HDMI output enabled and no rebooting)
        else:
            debug = False  # flag to enable debug mode (HDMI output enabled and no rebooting)

        if debuglevel > 20:
            # stop HDMI power (save energy)
            logger.info('HoneyPi ' + get_rpiscripts_version() +
                        ' Started on ' + get_pi_model() + ', Debuglevel: "' +
                        logging.getLevelName(debuglevel) +
                        '", Debuglevel logfile: "' +
                        logging.getLevelName(debuglevel_logfile) + '"')
            stop_tv()
            stop_hdd_led()
        else:
            logger.info('HoneyPi ' + get_rpiscripts_version() +
                        ' Started on ' + get_pi_model())
            start_hdd_led()

        runpostupgradescript()

        GPIO_BTN = settings["button_pin"]
        GPIO_LED = settings["led_pin"]

        # setup LED as output
        GPIO.setup(GPIO_LED, GPIO.OUT)

        # blink with LED on startup
        tblink = threading.Thread(target=blink_led, args=(GPIO_LED, ))
        tblink.start()

        # Call wvdial for surfsticks
        connect_internet_modem(settings)

        # check undervolate for since system start
        check_undervoltage()

        # start as seperate background thread
        # because Taster pressing was not recognised
        isMaintenanceActive = setStateToStorage('isMaintenanceActive', False)
        measurement_stop = threading.Event(
        )  # create event to stop measurement
        measurement = threading.Thread(target=start_measurement,
                                       args=(measurement_stop, ))
        measurement.start()  # start measurement

        # setup Button
        GPIO.setup(
            GPIO_BTN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN
        )  # Set pin 16 to be an input pin and set initial value to be pulled low (off)
        bouncetime = 100  # ignoring further edges for 100ms for switch bounce handling
        # register button press event
        GPIO.add_event_detect(GPIO_BTN,
                              GPIO.BOTH,
                              callback=button_pressed,
                              bouncetime=bouncetime)

        # Main Lopp: Cancel with STRG+C
        while True:
            time.sleep(
                0.2)  # wait 200 ms to give CPU chance to do other things
            pass

        print("This text will never be printed.")
    except Exception as ex:
        logger.critical("Unhandled Exception in main: " + repr(ex))
        if not debug:
            time.sleep(60)
            reboot()
def measure(offline, debug, channel, filtered_temperature, ds18b20Sensors,
            bme680Sensors, bme680IsInitialized, dhtSensors, tcSensors,
            bme280Sensors, weightSensors, hxInits, connectionErrors,
            measurementIsRunning):
    measurementIsRunning.value = 1  # set flag

    # filter the values out
    for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
        filter_temperatur_values(sensorIndex)

    # dict with all fields and values which will be tranfered to ThingSpeak later
    ts_fields = {}

    # measure every sensor with type 0
    for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
        # if we have at leat one filtered value we can upload
        if len(filtered_temperature[sensorIndex]) > 0 and 'ts_field' in sensor:
            ds18b20_temperature = filtered_temperature[sensorIndex].pop(
            )  # get last value from array
            ts_field_ds18b20 = sensor["ts_field"]
            if ts_field_ds18b20:
                ts_fields.update({ts_field_ds18b20: ds18b20_temperature})

    # measure BME680 (can only be one) [type 1]
    if bme680Sensors and len(bme680Sensors) == 1 and bme680IsInitialized:
        bme680_values = measure_bme680(bme680Sensors[0], 30)
        ts_fields.update(bme680_values)

    # measure every sensor with type 3 [DHT11/DHT22]
    for (i, sensor) in enumerate(dhtSensors):
        tempAndHum = measure_dht(sensor)
        ts_fields.update(tempAndHum)

    # measure every sensor with type 4 [MAX6675]
    for (i, sensor) in enumerate(tcSensors):
        tc_temp = measure_tc(sensor)
        ts_fields.update(tc_temp)

    # measure BME280 (can only be one) [type 5]
    if bme280Sensors and len(bme280Sensors) == 1:
        bme280_values = measure_bme280(bme280Sensors[0])
        ts_fields.update(bme280_values)

    start_single()
    # measure every sensor with type 2 [HX711]
    for (i, sensor) in enumerate(weightSensors):
        weight = measure_weight(sensor, hxInits[i])
        weight = compensate_temperature(sensor, weight, ts_fields)
        ts_fields.update(weight)
    stop_single()

    # print all measurement values stored in ts_fields
    for key, value in ts_fields.items():
        print(key + ": " + str(value))

    if len(ts_fields) > 0:
        if offline == 1 or offline == 3:
            try:
                s = write_csv(ts_fields)
                if s and debug:
                    error_log("Info: Data succesfully saved to CSV-File.")
            except Exception as ex:
                error_log(ex, "Exception")

        # if transfer to thingspeak is set
        if offline == 0 or offline == 1 or offline == 2:

            # do-while to retry failed transfer
            retries = 0
            connectionError = True
            while True:
                try:
                    # update ThingSpeak / transfer values
                    channel.update(ts_fields)
                    if debug:
                        error_log(
                            "Info: Data succesfully transfered to ThingSpeak.")
                    if connectionErrors.value > 0:
                        if debug:
                            error_log("Info: Connection Errors (" +
                                      str(connectionErrors.value) +
                                      ") Counting resetet.")
                        # reset connectionErrors because transfer succeded
                        connectionErrors.value = 0
                    # break do-while because transfer succeded
                    connectionError = False
                    break
                except requests.exceptions.HTTPError as errh:
                    error_log(errh, "Http Error")
                except requests.exceptions.ConnectionError as errc:
                    pass
                except requests.exceptions.Timeout as errt:
                    error_log(errt, "Timeout Error")
                except requests.exceptions.RequestException as err:
                    error_log(err, "Something Else")
                except Exception as ex:
                    error_log(ex, "Exception while sending Data")
                finally:
                    if connectionError:
                        print(
                            "Warning: Waiting for internet connection to try transfer again..."
                        )
                        wait_for_internet_connection(
                            15)  # wait before next try
                        retries += 1
                        # Maximum 3 retries
                        if retries >= 3:
                            break  # break do-while

            if connectionError:
                # Write to CSV-File if ConnectionError occured
                if offline == 2:
                    s = write_csv(ts_fields)
                    if s and debug:
                        error_log("Info: Data succesfully saved to CSV-File.")
                # Do Rebooting if to many connectionErrors in a row
                connectionErrors.value += 1
                error_log("Error: Failed internet connection. Count: " +
                          str(connectionErrors.value))
                if connectionErrors.value >= 5:
                    if not debug:
                        error_log(
                            "Info: Too many ConnectionErrors in a row => Rebooting"
                        )
                        time.sleep(4)
                        reboot()
                    else:
                        error_log(
                            "Info: Did not reboot because debug mode is enabled."
                        )

    elif debug:
        error_log("Info: No measurement data to send.")

    measurementIsRunning.value = 0  # clear flag
def start_measurement(measurement_stop):
    try:
        start_time = time.time()

        # load settings
        settings = get_settings()
        # ThingSpeak data
        channel_id = settings["ts_channel_id"]
        write_key = settings["ts_write_key"]
        interval = settings["interval"]
        debug = settings[
            "debug"]  # flag to enable debug mode (HDMI output enabled and no rebooting)
        shutdownAfterTransfer = settings["shutdownAfterTransfer"]
        offline = settings["offline"]  # flag to enable offline csv storage

        if debug:
            print("Debug-Mode is enabled.")
            error_log("Info: The measurements have started.")

        # with process shared variables
        connectionErrors = Value('i', 0)
        measurementIsRunning = Value('i', 0)

        if interval and not isinstance(
                interval,
                int) or interval == 0 or not channel_id or not write_key:
            error_log(
                "Info: No measurement because ThingSpeak settings are not complete or measurement interval is null."
            )
            measurement_stop.set()

        # read configured sensors from settings.json
        ds18b20Sensors = get_sensors(settings, 0)
        bme680Sensors = get_sensors(settings, 1)
        weightSensors = get_sensors(settings, 2)
        dhtSensors = get_sensors(settings, 3)
        tcSensors = get_sensors(settings, 4)
        bme280Sensors = get_sensors(settings, 5)

        # -- Run Pre Configuration --
        # if bme680 is configured
        if bme680Sensors and len(bme680Sensors) == 1:
            bme680IsInitialized = initBME680FromMain()
        else:
            bme680IsInitialized = 0

        # if hx711 is set
        hxInits = []
        for (i, sensor) in enumerate(weightSensors):
            _hx = init_hx711(sensor, debug)
            hxInits.append(_hx)

        # ThingSpeak channel
        channel = thingspeak.Channel(id=channel_id, write_key=write_key)

        # start at -6 because we want to get 6 values before we can filter some out
        counter = -6
        time_measured = 0
        while not measurement_stop.is_set():
            counter += 1

            # read values from sensors every second
            for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
                checkIfSensorExistsInArray(sensorIndex)
                if 'device_id' in sensor:
                    read_unfiltered_temperatur_values(sensorIndex,
                                                      sensor['device_id'])

            # wait seconds of interval before next check
            # free ThingSpeak account has an upload limit of 15 seconds
            time_now = time.time()
            isTimeToMeasure = (time_now - time_measured >= interval
                               ) and counter > 0  # old: counter%interval == 0
            if isTimeToMeasure or interval == 1:
                now = time.strftime("%H:%M", time.localtime(time_now))
                lastMeasurement = time.strftime("%H:%M",
                                                time.localtime(time_measured))
                if time_measured == 0:
                    print("First time measurement. Now: " + str(now))
                else:
                    print("Last measurement was at " + str(lastMeasurement))
                    print("Time over for a new measurement. Time is now: " +
                          str(now))
                time_measured = time.time()

                if measurementIsRunning.value == 0:
                    q = Queue()
                    p = Process(target=measure,
                                args=(offline, debug, channel,
                                      filtered_temperature, ds18b20Sensors,
                                      bme680Sensors, bme680IsInitialized,
                                      dhtSensors, tcSensors, bme280Sensors,
                                      weightSensors, hxInits, connectionErrors,
                                      measurementIsRunning))
                    p.start()
                    p.join()
                else:
                    error_log(
                        "Warning: Forerun measurement is not finished yet. Consider increasing interval."
                    )

                # stop measurements after uploading once
                if interval == 1:
                    print("Only one measurement was set => stop measurements.")
                    measurement_stop.set()

                    if shutdownAfterTransfer:
                        print(
                            "Shutting down was set => Waiting 10seconds and then shutdown."
                        )
                        time.sleep(10)
                        shutdown()

            time.sleep(6)  # wait 6 seconds before next measurement check

        end_time = time.time()
        time_taken = end_time - start_time  # time_taken is in seconds
        time_taken_s = float(
            "{0:.2f}".format(time_taken))  # remove microseconds
        print("Measurement-Script runtime was " + str(time_taken_s) +
              " seconds.")

    except Exception as e:
        error_log(e, "Unhandled Exception while Measurement")
        if not debug:
            time.sleep(10)
            reboot()
def measure(offline, debug, ts_channels, ts_server_url, filtered_temperature,
            ds18b20Sensors, bme680Sensors, bme680IsInitialized, dhtSensors,
            aht10Sensors, sht31Sensors, hdc1008Sensors, tcSensors,
            bme280Sensors, voltageSensors, ee895Sensors, weightSensors,
            hxInits, connectionErrors, measurementIsRunning):
    measurementIsRunning.value = 1  # set flag
    ts_fields = {}
    try:
        ts_fields = measure_all_sensors(
            debug, filtered_temperature, ds18b20Sensors, bme680Sensors,
            bme680IsInitialized, dhtSensors, aht10Sensors, sht31Sensors,
            hdc1008Sensors, tcSensors, bme280Sensors, voltageSensors,
            ee895Sensors, weightSensors, hxInits)
        if len(ts_fields) > 0:
            if offline == 1 or offline == 3:
                try:
                    s = write_csv(ts_fields, ts_channels)
                    if s and debug:
                        error_log("Info: Data succesfully saved to CSV-File.")
                except Exception as ex:
                    error_log(ex, "Exception in measure (1)")

            # if transfer to thingspeak is set
            if (offline == 0 or offline == 1 or offline == 2) and ts_channels:
                # update ThingSpeak / transfer values
                connectionErrorHappened = manage_transfer_to_ts(
                    ts_channels, ts_fields, ts_server_url, offline, debug)

                if connectionErrorHappened:
                    MAX_RETRIES_IN_A_ROW = 3
                    # Do Rebooting if to many connectionErrors in a row
                    connectionErrors.value += 1
                    error_log("Error: Failed internet connection. Count: " +
                              str(connectionErrors.value) + "/" +
                              str(MAX_RETRIES_IN_A_ROW))
                    if connectionErrors.value >= MAX_RETRIES_IN_A_ROW:
                        if not debug:
                            error_log(
                                "Warning: Too many Connection Errors in a row => Rebooting Raspberry"
                            )
                            time.sleep(4)
                            reboot()
                        else:
                            error_log(
                                "Info: Did not reboot because debug mode is enabled."
                            )
                else:
                    if connectionErrors.value > 0:
                        if debug:
                            error_log(
                                "Info: Connection Errors (" +
                                str(connectionErrors.value) +
                                ") Counting resetet because transfer succeded."
                            )
                        # reset connectionErrors because transfer succeded
                        connectionErrors.value = 0

        elif debug:
            error_log("Info: No measurement data to send.")

        measurementIsRunning.value = 0  # clear flag

    except Exception as ex:
        error_log(ex, "Exception during measure (2)")
        measurementIsRunning.value = 0  # clear flag
def start_measurement(measurement_stop):
    try:
        print("The measurements have started.")
        start_time = time.time()

        # load settings
        settings = get_settings()
        # ThingSpeak data
        channel_id = settings["ts_channel_id"]
        write_key = settings["ts_write_key"]
        interval = settings["interval"]

        if interval and not isinstance(
                interval,
                int) or interval == 0 or not channel_id or not write_key:
            print("ThingSpeak settings are not complete or interval is 0")
            measurement_stop.set()

        # read configured sensors from settings.json
        ds18b20Sensors = get_sensors(settings, 0)
        bme680Sensors = get_sensors(settings, 1)
        weightSensors = get_sensors(settings, 2)
        dhtSensors = get_sensors(settings, 3)

        # if bme680 is configured
        if bme680Sensors and len(bme680Sensors) == 1:
            gas_baseline = None
            if initBME680FromMain():
                # bme680 sensor must be burned in before use
                gas_baseline = burn_in_bme680(30)

                # if burning was canceled => exit
                if gas_baseline is None:
                    print("gas_baseline can't be None")

        # ThingSpeak channel
        channel = thingspeak.Channel(id=channel_id, write_key=write_key)

        # counting connection Errors
        connectionErros = 0

        # start at -6 because we want to get 6 values before we can filter some out
        counter = -6
        while not measurement_stop.is_set():

            # read values from sensors every second
            for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
                checkIfSensorExistsInArray(sensorIndex)
                if 'device_id' in sensor:
                    read_unfiltered_temperatur_values(sensorIndex,
                                                      sensor['device_id'])

            # for testing:
            #try:
            #    weight = measure_weight(weightSensors[0])
            #    print("weight: " + str(list(weight.values())[0]))
            #except IOError:
            #    print "IOError occurred"
            #except TypeError:
            #    print "TypeError occurred"
            #except IndexError:
            #    print "IndexError occurred"

            # wait seconds of interval before next check
            # free ThingSpeak account has an upload limit of 15 seconds
            if counter % interval == 0:
                print("Time over for a new measurement.")

                # filter the values out
                for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
                    filter_temperatur_values(sensorIndex)

                # dict with all fields and values which will be tranfered to ThingSpeak later
                ts_fields = {}

                # measure every sensor with type 0
                for (sensorIndex, sensor) in enumerate(ds18b20Sensors):
                    # if we have at leat one filtered value we can upload
                    if len(filtered_temperature[sensorIndex]
                           ) > 0 and 'ts_field' in sensor:
                        ds18b20_temperature = filtered_temperature[
                            sensorIndex].pop()  # get last value from array
                        ts_field_ds18b20 = sensor["ts_field"]
                        if ts_field_ds18b20:
                            ts_fields.update(
                                {ts_field_ds18b20: ds18b20_temperature})

                # measure BME680 (can only be once) [type 1]
                if bme680Sensors and len(bme680Sensors) == 1 and gas_baseline:
                    bme680_values = measure_bme680(gas_baseline,
                                                   bme680Sensors[0])
                    ts_fields.update(bme680_values)

                # measure every sensor with type 2 [HX711]
                for (i, sensor) in enumerate(weightSensors):
                    weight = measure_weight(sensor)
                    ts_fields.update(weight)

                # measure every sensor with type 3 [DHT11/DHT22]
                for (i, sensor) in enumerate(dhtSensors):
                    tempAndHum = measure_dht(sensor)
                    ts_fields.update(tempAndHum)

                # print measurement values for debug reasons
                for key, value in ts_fields.iteritems():
                    print key + ": " + str(value)

                try:
                    # update ThingSpeak / transfer values
                    if len(ts_fields) > 0:
                        channel.update(ts_fields)
                        # reset connectionErros because transfer succeded
                        connectionErros = 0
                except requests.exceptions.HTTPError as errh:
                    error_log(errh, "Http Error")
                except requests.exceptions.ConnectionError as errc:
                    error_log(errc, "Error Connecting")
                    connectionErros += 1
                    # multiple connectionErrors in a row => Exception
                    if connectionErros > 4:
                        raise MyRebootException
                except requests.exceptions.Timeout as errt:
                    error_log(errt, "Timeout Error")
                except requests.exceptions.RequestException as err:
                    error_log(err, "Something Else")

            counter += 1
            sleep(0.96)

        end_time = time.time()
        time_taken = end_time - start_time  # time_taken is in seconds
        time_taken_s = float(
            "{0:.2f}".format(time_taken))  # remove microseconds
        print("Measurement-Script runtime was " + str(time_taken_s) +
              " seconds.")

    except MyRebootException as re:
        error_log(re, "Too many ConnectionErrors in a row => Rebooting")
        time.sleep(1)
        reboot()
    except Exception as e:
        error_log(e, "Unhandled Exception while Measurement")
        time.sleep(60)
        reboot()