| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215 | #!/usr/bin/python3 -u# -*- coding: utf-8 -*-#import serialimport timefrom time import localtime, strftimefrom datetime import datetimeimport configparserfrom influxdb import InfluxDBClientimport osimport sysimport paho.mqtt.client as mqttimport yamlimport jsonimport statisticsimport mathfrom time import sleep#import math#import numpy as np#import httplib# Change working dir to the same dir as this scriptos.chdir(sys.path[0])# stop program if nothing is received from JeeLink for 5 min (will be restarted by systemd)serialReceived_maxAge = 300config = configparser.ConfigParser()config.read('jeelinklog.ini')serialport = config['jeelink'].get('serialport')serialbaud = int(config['jeelink'].get('baudrate'))if config['jeelink'].get('initTimeout') != None:    serialInitTimeout = int(config['jeelink'].get('initTimeout'))else:    serialInitTimeout = 2jeelinkInitCmd = config['jeelink'].get('initCmd')if jeelinkInitCmd == None:    jeelinkInitCmd = "30t 3m v" # init cmd for TX29 AND TX35 sensors (17.241 and 9.579 kbps toggle every 30s)    #jeelinkInitCmd = "0t 1m v" # init cmd for TX29 sensors only (17.241 kbps, no toggle)mqtt_topic_prefix = config['mqtt'].get('topic_prefix')topic_prefix_outside_temphum = config['mqtt'].get('topic_prefix_outside_temphum')mqtt_topic_atemp = config['mqtt'].get('topic_outside_temp')mqtt_topic_ahum = config['mqtt'].get('topic_outside_hum')mqtt_topic_ahum = config['mqtt'].get('topic_outside_dew')mqtt_topic_ahum = config['mqtt'].get('topic_outside_abshum')mqtt_topic_domoticz_in = "domoticz/in"mqtt_subtopic_notify = config['mqtt'].get('subtopic_notify')logfile_new_sensors = config['main'].get('logfile_new_sensors')path_new_sensors_folder = config['main'].get('path_new_sensors_folder')log_path = config['main'].get('log_path')if not os.path.exists(log_path):    os.makedirs(log_path)verbosemode = False#sensors_conf_file = "/home/pi/jeelink_sensors.csv"sensordata_maxage = int(config['sensors'].get('data_maxage'))#minUpdateInterval = 60#aTempHumPublishInterval = 60#override_updateinterval_on_change = False#atemp_sensor_idx = 94#atemp_sensor_idx_2 = 113average_value_steps = int(config['sensors'].get('average_value_steps'))if average_value_steps == 0:    average_value_steps = 1if len(sys.argv) > 1 and str(sys.argv[1]) == "-v":    verbosemode = True    def touch(fname, times=None):    with open(fname, 'a'):        os.utime(fname, times)def on_connect(client, userdata, flags, rc):    if verbosemode:        print("MQTT connected with result code " + str(rc) + "\n")    #client.subscribe("wetter/atemp")def on_disconnect(client, userdata, rc):    if rc != 0:        print("Unexpected MQTT disconnection. Will auto-reconnect\n")        #def on_message(client, userdata, msg):#    #print(msg.topic + " " + str(msg.payload))#    global atemp#    atemp = msg.payload# dont edit below#starting values only..##atemp = 61 ##ahum = 101##atemp1 = 61##ahum1 = 101##atemp2 = 61##ahum2 = 101##atemp_last = 61##ahum_last = 101checkLastUpdateInterval = 60checkLastUpdateInterval_lastRun = 0lastPublishTime = 0lastStoreTime = 0sensors = dict()sensors_id_to_name = dict()#sensors_idx = dict()sensors_lastTemp = dict()sensors_lastHum = dict()sensors_lastUpdate = dict()sensors_lastReceivedValue_temp = dict()sensors_lastReceivedTime = dict()sensors_lastValues_temp = dict()sensors_lastValues_hum = dict()sensors_lastAvgValue_temp = dict()sensors_lastAvgValue_hum = dict()sensors_lastValues_lastIndex = dict()#sensors_unavailable = dict()sensors_batteryState = dict()sensors_new_alreadyNotified = dict()sensors_outside_sensors = []outSens_lastRun = 0outSens_store_lastRun = 0influx_default_fieldname_temperature = 'Temperature'influx_default_fieldname_humidity = 'Humidity'influx_default_fieldname_dewpoint = 'Dewpoint'influx_default_fieldname_abshum = 'AbsHumidity'influx_default_datatype_temperature = 'float'influx_default_datatype_humidity = 'int'influx_default_datatype_dewpoint = 'float'influx_default_datatype_abshum = 'float'sensors_yaml = yaml.load(open(config['main'].get('sensors_config_yml')), Loader=yaml.FullLoader)def list_duplicates(seq):  seen = set()  seen_add = seen.add  # adds all elements it doesn't know yet to seen and all other to seen_twice  seen_twice = set( x for x in seq if x in seen or seen_add(x) )  # turn the set into a list (as requested)  return list( seen_twice )  # Dew point calculation based on formula and JS code found on: https://www.wetterochs.de/wetter/feuchte.html#f4# dew point from temperature, relative humidity# in °Cdef dewpoint(temp, relHum):    if temp >= 0:        a = 7.5        b = 237.3    else:        a = 7.6        b = 240.7    c = math.log(vaporPressure(temp, relHum)/6.1078) * math.log10(math.e)    return (b * c) / (a - c)    def celsiusToKelvin(temp):    return temp + 273.15    def absoluteHumidity(relHum, temp):    # AF = absolute Feuchte in g Wasserdampf pro m3 Luft    # R* = 8314.3 J/(kmol*K) (universelle Gaskonstante)    # mw = 18.016 kg/kmol (Molekulargewicht des Wasserdampfes)    # r = relative Luftfeuchte    # T = Temperatur in °C    # TK = Temperatur in Kelvin (TK = T + 273.15)    # TD = Taupunkttemperatur in °C    #    # mw/R* = 18.016 / 8314.3 = 0,0021668691290908    #     # AF(r,TK)  = 10^5 * mw/R* * DD(T,r)/TK    # unused 2nd formula: AF(TD,TK) = 10^5 * mw/R* * SDD(TD)/TK    mw = 18.016    R = 8314.3    return 10**5 * mw/R * vaporPressure(temp, relHum) / celsiusToKelvin(temp)    # Saettingungsdampfdruck / saturation vapour pressure# from temperature in hPadef saturationVaporPressure(temp):    if temp >= 0:        a = 7.5        b = 237.3    else:        a = 7.6        b = 240.7    return 6.1078 * math.exp(((a*temp)/(b + temp))/ math.log10(math.e))    # Dampfdruck / vapour pressure# from temperature, relative humidity in hPadef vaporPressure(temp, relHum):	return relHum/100 * saturationVaporPressure(temp)    if verbosemode:    print("JeeLink2MQTT by Flo Kra")    print("=======================================================================")    print()    print("JeeLink initCmd: " + jeelinkInitCmd)    print()    print()# load InfluxDB configuration influxdb_yaml = yaml.load(open(config['main'].get('influx_config_yml')), Loader=yaml.SafeLoader)if verbosemode:     print("loading InfluxDB configuration...")    print("InfluxDB Instances:")    print(json.dumps(influxdb_yaml, indent=4))influxclient = dict()for instance in influxdb_yaml:    i_host = influxdb_yaml[instance].get('host', None)    i_port = int(influxdb_yaml[instance].get('port', 8086))    i_username = influxdb_yaml[instance].get('username', None)    i_password = influxdb_yaml[instance].get('password', None)    i_database = influxdb_yaml[instance].get('database', None)    if i_host != None and i_database != None:        if i_username != None and i_password != None:            influxclient[instance] = InfluxDBClient(i_host, i_port, i_username, i_password, i_database)        else:            influxclient[instance] = InfluxDBClient(i_host, i_port, i_database)if verbosemode:     print()    print()# load sensors configurationif verbosemode:        print("loading sensors configuration: ")    print(json.dumps(sensors_yaml, indent=3))    print()for key in sensors_yaml:    #print(key, '->', sensors_yaml[key])    if verbosemode: print("Sensor name:", key)    sensorName = key        if sensors_yaml[key].get('LaCrosseID') >= 0:        if verbosemode: print("LaCrosseID:", sensors_yaml[key].get('LaCrosseID'))        sensorId = sensors_yaml[key].get('LaCrosseID')        sensors_id_to_name[sensorId] = sensorName                if sensors_yaml[key].get('DomoticzIdx'):            if verbosemode: print("DomoticzIdx:", sensors_yaml[key].get('DomoticzIdx'))            #sensors_idx[sensorId] = sensors_yaml[key].get('DomoticzIdx')                    if sensors_yaml[key].get('Topic_Temp'):            if verbosemode: print("Topic_Temp:", sensors_yaml[key].get('Topic_Temp'))                    if sensors_yaml[key].get('Topic_Hum'):            if verbosemode: print("Topic_Hum:", sensors_yaml[key].get('Topic_Hum'))                if sensors_yaml[key].get('InfluxDB_Instance'):            if verbosemode:                 print("InfluxDB_Instance:", sensors_yaml[key].get('InfluxDB_Instance'))            if sensors_yaml[key].get('InfluxDB_Instance') not in influxdb_yaml:                print("Error: invalid InfluxDB instance '" + sensors_yaml[key].get('InfluxDB_Instance') + "' configured for sensor '" + sensorName + "'")                    if sensors_yaml[key].get('isOutsideTempSensor'):            if verbosemode: print("isOutsideTempSensor:", sensors_yaml[key].get('isOutsideTempSensor'))            sensors_outside_sensors.append(sensorId)            else:         print("WARNING: Sensor " + key + " has no LaCrosseID!")        if verbosemode:         print()    if verbosemode:     print()    print()    #print(json.dumps(sensor))#print("sensors_id_to_name =",sensors_id_to_name)#print("outside sensors: ", sensors_outside_sensors)        mqttc = mqtt.Client()mqttc.on_connect = on_connectmqttc.on_disconnect = on_disconnect##mqttc.on_message = on_messageif config['mqtt'].get('user') != "" and config['mqtt'].get('password') != "":    mqttc.username_pw_set(config['mqtt'].get('user'), config['mqtt'].get('password'))mqttc.connect(config['mqtt'].get('server'), config['mqtt'].getint('port'), 60)mqttc.loop_start()#mqttc.loop_forever()ser = serial.Serial(port=serialport,    baudrate = serialbaud,    parity=serial.PARITY_NONE,    stopbits=serial.STOPBITS_ONE,    bytesize=serial.EIGHTBITS,    timeout=1)checkLastUpdateInterval_lastRun = time.time() # first check after timeout expired# set serialReceivedLastTime to current time so that we can detect if nothing is received for some timeserialReceivedLastTime = int(time.time())# init JeeLink devicesleep(serialInitTimeout)ser.flushInput()ser.write(jeelinkInitCmd.encode('ascii')) # send init command to Jeelink#ser.write('v\r\n'.encode('ascii'))  # get JeeLink version infosleep(0.2)try:    while True:        msg_was_sent = 0                #clear serial buffer to remove junk and noise        ###ser.flushInput()                #read buffer until cr/lf        serLine = ser.readline().strip()        # catch exception on invalid char coming in: UnicodeDecodeError: 'ascii' codec can't decode byte 0xf4 in position 6: ordinal not in range(128)        try:             serLine = serLine.decode('ascii')        except:            serLine = False        if(serLine):            if serLine.find('LaCrosseITPlusReader') != -1:                if verbosemode:                    print("Jeelink version/config: " + serLine)                    print()                    print()                            elif serLine.find('OK 9') != -1:                                # set serialReceivedLastTime to current time so that we can detect if nothing is received for some time                serialReceivedLastTime = int(time.time())                                if verbosemode:                    print("RX: " + serLine + " => LaCrosse sensor")                # uns interessieren nur reinkommende Zeilen die mit "OK 9 " beginnen                                # 0  1 2  3   4   5   6                # OK 9 ID XXX XXX XXX XXX                # |  | |  |   |   |   |                # |  | |  |   |   |   --- Humidity incl. WeakBatteryFlag                # |  | |  |   |   |------ Temp * 10 + 1000 LSB                # |  | |  |   |---------- Temp * 10 + 1000 MSB                # |  | |  |-------------- Sensor type (1 or 2) +128 if NewBatteryFlag                # |  | |----------------- Sensor ID                # |  |------------------- fix "9"                # |---------------------- fix "OK"                                serLineParts = serLine.split(' ')                                #print("Len: " + str(len(serLineParts)))                                if(len(serLineParts) == 7): # check correct size of incoming data                                    #addr = serLineParts[2]                    #addr = "{0:x}".format(int(serLineParts[2]))                    #addr = hex((int(serLineParts[2])))                    addr = int(serLineParts[2])                    addrhex = "{0:x}".format(int(serLineParts[2]))                                                                lastUpdate = sensors_lastUpdate.get(addr, None)                    lastTemp = sensors_lastTemp.get(addr, None)                    lastHum = sensors_lastHum.get(addr, None)                                        currentsensor_name = sensors_id_to_name.get(addr, None)                                                                                                # extract sensor data received from JeeLink                    if int(serLineParts[3]) >= 128:                         batt_new = 1                        type = int(serLineParts[3]) - 128                    else:                        batt_new = 0                        type = int(serLineParts[3])                                        temp = (int(serLineParts[4])*256 + int(serLineParts[5]) - 1000)/10.0                                        if int(serLineParts[6]) >= 128:                         batt_low = 1                        hum = int(serLineParts[6]) - 128                    else:                        batt_low = 0                        hum = int(serLineParts[6])                        if hum > 100:                             hum = 100                                        if batt_new == 1:                        sensors_batteryState[addr] = 2                    elif batt_low == 1:                        sensors_batteryState[addr] = 1                    else:                        sensors_batteryState[addr] = 0                                        lastValues_lastIndex = sensors_lastValues_lastIndex.get(addr, None)                                        if sensors_lastValues_temp.get(addr, None) == None:                        sensors_lastValues_temp[addr] = [None] * average_value_steps                                        if sensors_lastValues_hum.get(addr, None) == None:                        sensors_lastValues_hum[addr] = [None] * average_value_steps                                        data_okay = False                                        if sensors_lastReceivedValue_temp.get(addr, None) == None:                        # this is the first time we receive from that sensor in that session                        if verbosemode: print("first received from sensor",str(addr))                        sensors_lastReceivedValue_temp[addr] = temp                        sensors_lastReceivedTime[addr] = int(time.time())                        #lastValues_lastIndex = 0                    else:                        lastValue = sensors_lastReceivedValue_temp.get(addr, None)                                                max_off_value = float(config['sensors'].get('max_off_value'))                        ignore_off_value_timeout = int(config['sensors'].get('ignore_off_value_timeout'))                                                if lastValue != None and ((temp >= (lastValue - max_off_value) and temp <= (lastValue + max_off_value)) or ((int(time.time()) - sensors_lastReceivedTime.get(addr)) > ignore_off_value_timeout)):   # discard off values                            sensors_lastReceivedValue_temp[addr] = temp                            sensors_lastReceivedTime[addr] = int(time.time())                            #print("Last Value=",lastValue,"currValue=",temp)                            data_okay = True                        else:                            if verbosemode: print("skipped sensor reading - Last Value=",lastValue,"currValue=",temp)                                                                    if data_okay:                        if lastValues_lastIndex == None:                            lastValues_lastIndex = 0                        elif lastValues_lastIndex == (average_value_steps - 1):                            lastValues_lastIndex = 0                        else:                            lastValues_lastIndex += 1                        if verbosemode: print("lastValues_lastIndex =", lastValues_lastIndex)                                                sensors_lastValues_lastIndex[addr] = lastValues_lastIndex                        sensors_lastValues_temp[addr][lastValues_lastIndex] = temp                        sensors_lastValues_hum[addr][lastValues_lastIndex] = hum                                                sensors_lastUpdate[addr] = int(time.time())                                                if verbosemode: print("sensors_lastValues_temp =", sensors_lastValues_temp[addr])                                                                if currentsensor_name is None:                         if batt_new == 1 and not sensors_new_alreadyNotified.get('addr', False):                            notifystr = "NEW sensor with ID " + str(addr)                            mqttc.publish(mqtt_topic_prefix+"/" + mqtt_subtopic_notify, notifystr, qos=0, retain=False)                                                        if not os.path.exists(log_path+'/new'):                                os.makedirs(log_path+'/new')                                                            fname = log_path + '/new/' + str(addr)                            if not os.path.exists(fname):                                try:                                    touch(fname)                                except:                                    pass                                                        try:                                f = open(log_path+'/'+logfile_new_sensors, 'a')                                f.write(str(datetime.now())+": "+notifystr+"\n")                                f.close()                            except:                                # guat dann hoit ned...                                pass                                                            sensors_new_alreadyNotified[addr] = True                        else:                            if not os.path.exists(log_path+'/unknown'):                                os.makedirs(log_path+'/unknown')                            fname = log_path + '/unknown/' + str(addr)                            if not os.path.exists(fname):                                try:                                    touch(fname)                                except:                                    pass                                                if verbosemode:                            print("unknown sensor ID " + str(addr))                                                            if verbosemode:                        print("LaCrosse-ID: " + str(addr) + " = 0x" + str(addrhex) + "   Type: " + str(type) + "   Batt_New: " + str(batt_new) + "   Batt_Low: " + str(batt_low) + "   Temp: " + str(temp) + "   Hum: " + str(hum) + "   Name: " + str(currentsensor_name))                        print()                                        #if senddata:                    #    sensors_lastUpdate[str(addr)] = int(time.time())                    #    sensors_lastTemp[str(addr)] = temp                    #    sensors_lastHum[str(addr)] = hum                    #                        #    isAtemp = False                    #    if int(currentsensor_idx) == atemp_sensor_idx:                    #        atemp1 = temp                    #        ahum1 = hum                    #        isAtemp = True                    #    elif int(currentsensor_idx) == atemp_sensor_idx_2:                    #        atemp2 = temp                    #        ahum2 = hum                    #        isAtemp = True                    #                        #    if isAtemp:                    #        if atemp1 <= atemp2:                    #            atemp = atemp1                    #            ahum = ahum1                    #        else:                    #            atemp = atemp2                    #            ahum = ahum2                    #                            #        if atemp < 61 and ahum < 101:                    #            if atemp != atemp_last or ahum != ahum_last or ((time.time() - atemphum_lastUpdate) > aTempHumPublishInterval):                    #                atemphum_lastUpdate = time.time()                    #                atemp_last = atemp                    #                ahum_last = ahum                    #                mqttc.publish(mqtt_topic_atemp, str(atemp), qos=0, retain=True)                    #                mqttc.publish(mqtt_topic_ahum, str(ahum), qos=0, retain=True)                    #                mqttc.publish(mqtt_topic_atemphum_lastUpdate, strftime("%Y-%m-%d %H:%M:%S", localtime()), qos=0, retain=False)                    #                        #    domoticz_json = "{\"idx\":" + str(currentsensor_idx) + ",\"nvalue\":0,\"svalue\":\"" + str(temp) + ";" + str(hum) + ";1\"}"                    #    #if verbosemode:                    #    #    print(domoticz_json)                    #    mqttc.publish(mqtt_topic_domoticz_in, domoticz_json, qos=0, retain=False)                    #                        #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/temperature", str(temp), qos=0, retain=False)                    #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/humidity", str(hum), qos=0, retain=False)                    #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/battery", str(batterystate), qos=0, retain=False)                    #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/lastUpdate", strftime("%Y-%m-%d %H:%M:%S", localtime()), qos=0, retain=False)                    #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/availability", "available", qos=0, retain=False)                    #                        #    lacrosse_json = "{\"temperature\":" + str(temp) + ", \"humidity\":" + str(hum) + ", \"battery\":\"" + str(batterystate) + "\"}"                    #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/json", lacrosse_json, qos=0, retain=False)                    #                        #    tmptext = str(temp) + "° " + str(hum) + "%"                    #    mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/TempHumText", tmptext, qos=0, retain=False)                    #                        #    if verbosemode:                    #        print("MQTT published")                    #                    #    try:                    #        touch("/tmp/jeelink2mqtt_running")                    #    except:                    #        # guat dann ned...                    #        pass                    #                    #else:                    #    if verbosemode:                    #        if currentsensor_name is None:                     #            print("MQTT published")                    #        else:                    #            print("MQTT publishing surpressed (interval not expired)")                    #                    #                    #if verbosemode:                    #    print("\n")                                    else:                    if verbosemode: print("RX: " + serLine + " => ignored invalid data")                    pass            else:                if verbosemode:                     print("RX: " + serLine)                pass                        # publish on MQTT on set interval        publishNow = False        if (int(time.time()) - lastPublishTime) > int(config['sensors'].get('publish_interval')):            if lastPublishTime == 0:                lastPublishTime = int(time.time())            else:                publishNow = True                lastPublishTime = int(time.time())                                #for sensor in                 #sensors_lastReceivedTime[str(addr)]                    # store to InfluxDB on set interval        storeNow = False        if (int(time.time()) - lastStoreTime) > int(config['sensors'].get('store_interval')):            if lastStoreTime == 0:                lastStoreTime = int(time.time())            else:                storeNow = True                lastStoreTime = int(time.time())                if publishNow or storeNow:            #print("available sensor data: ", sensors_lastUpdate)            for id in sensors_lastUpdate:                            if (time.time() - sensors_lastUpdate[id]) < sensordata_maxage:                    s_name = sensors_id_to_name.get(id, None)                    if verbosemode: print("current data available for:", id, s_name)                                        sensorDataComplete = True                                        sum_temp=0                    for val in sensors_lastValues_temp[id]:                        if val is None:                            sensorDataComplete = False                        else:                            sum_temp = sum_temp + val                                                sum_hum=0                    for val in sensors_lastValues_hum[id]:                        if val is None:                            sensorDataComplete = False                        else:                            sum_hum = sum_hum + val                                        if sensorDataComplete:                        s_currAvgTemp = round(sum_temp / len(sensors_lastValues_temp[id]), 1)                        s_currAvgHum = int(sum_hum / len(sensors_lastValues_hum[id]))                                                # calc dewpoint                        if config['sensors'].getboolean('calculate_dewpoint', False):                            s_currDewpoint = round(dewpoint(s_currAvgTemp, s_currAvgHum), 1)                                                # calc absolute humidity                        if config['sensors'].getboolean('calculate_absolute_humidity', False):                            s_currAbsHum = round(absoluteHumidity(s_currAvgHum, s_currAvgTemp), 2)                                                sensors_lastAvgValue_temp[id] = s_currAvgTemp                        sensors_lastAvgValue_hum[id] = s_currAvgHum                                                if verbosemode: print("s_currAvgTemp =", s_currAvgTemp, "s_currAvgHum =", s_currAvgHum)                    else:                        if verbosemode: print("s_currAvgTemp/s_currAvgHum: not yet enough readings available")                                        if sensorDataComplete:                                                # as Home Assistant MQTT binary sensor can only work with 2 states (unless using value templates):                        #   -> removed "NEW" state string from /battery topic and added /batteryNew topic                        if sensors_batteryState.get(id,None) == 2:                            s_battNew = True                            s_battState = "OK"                        elif sensors_batteryState.get(id, None) == 1:                            s_battNew = False                            s_battState = "LOW"                        elif sensors_batteryState.get(id, None) == 0:                            s_battNew = False                            s_battState = "OK"                                                if s_battNew:                            s_battNew_str = "YES"                        else:                            s_battNew_str = "NO"                                                if s_name is not None:                            s_domIdx = sensors_yaml[s_name].get('DomoticzIdx', None)                            s_topic_temp = sensors_yaml[s_name].get('Topic_Temp', None)                            s_topic_hum = sensors_yaml[s_name].get('Topic_Hum', None)                            s_topic_dew = sensors_yaml[s_name].get('Topic_Dew', None)                            s_topic_absHum = sensors_yaml[s_name].get('Topic_AbsHum', None)                            s_influxInstance = sensors_yaml[s_name].get('InfluxDB_Instance', None)                            s_isOutsideTempSensor = sensors_yaml[s_name].get('isOutsideTempSensor', None)                                                        if s_domIdx is not None and publishNow:                                domoticz_json = "{\"idx\":" + str(s_domIdx) + ",\"nvalue\":0,\"svalue\":\"" + str(s_currAvgTemp) + ";" + str(s_currAvgHum) + ";1\"}"                                if verbosemode:                                    print("Domoticz JSON:", domoticz_json)                                mqttc.publish(mqtt_topic_domoticz_in, domoticz_json, qos=0, retain=False)                                                            if s_topic_temp is not None and len(s_topic_temp)>5 and publishNow:                                if verbosemode: print("publishing temp on ", s_topic_temp)                                mqttc.publish(s_topic_temp, str(s_currAvgTemp), qos=0, retain=False)                                                            if s_topic_dew is not None and len(s_topic_dew)>5 and publishNow and config['sensors'].getboolean('calculate_dewpoint', False):                                 if verbosemode: print("publishing dewpoint on ", s_topic_dew)                                mqttc.publish(s_topic_dew, str(s_currDewpoint), qos=0, retain=False)                                                        if s_topic_absHum is not None and len(s_topic_absHum)>5 and publishNow and config['sensors'].getboolean('calculate_absolute_humidity', False):                                if verbosemode: print("publishing absolute humidty on ", s_topic_absHum)                                mqttc.publish(s_topic_absHum, str(s_currAbsHum), qos=0, retain=False)                                                                                        if s_topic_hum is not None and len(s_topic_hum)>5 and publishNow:                                if verbosemode: print("publishing hum on ", s_topic_temp)                                mqttc.publish(s_topic_hum, str(s_currAvgHum), qos=0, retain=False)                                                        if publishNow:                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/temperature", str(s_currAvgTemp), qos=0, retain=False)                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/humidity", str(s_currAvgHum), qos=0, retain=False)                                                                if config['sensors'].getboolean('calculate_dewpoint', False):                                    mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/dewpoint", str(s_currDewpoint), qos=0, retain=False)                                if config['sensors'].getboolean('calculate_absolute_humidity', False):                                    mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/absoluteHumidity", str(s_currAbsHum), qos=0, retain=False)                                                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/battery", s_battState, qos=0, retain=False)                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/batteryNew", s_battNew_str, qos=0, retain=False)                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/availability", "available", qos=0, retain=False)                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/lastUpdate", strftime("%Y-%m-%d %H:%M:%S", localtime()), qos=0, retain=False)                                                                # publish global lastUpdate for monitoring purposes                                mqttc.publish(mqtt_topic_prefix+"/lastUpdate", strftime("%Y-%m-%d %H:%M:%S", localtime()), qos=0, retain=False)                                                                # JSON output                                lacrosse_json = "{\"temperature\":" + str(s_currAvgTemp) \                                    + ", \"humidity\":" + str(s_currAvgHum) \                                    + ", \"battery\":\"" + str(s_battState) + "\""                                                                    if config['sensors'].getboolean('calculate_dewpoint', False):                                    lacrosse_json = lacrosse_json + ", \"dewpoint\":" + str(s_currDewpoint)                                if config['sensors'].getboolean('calculate_absolute_humidity', False):                                    lacrosse_json = lacrosse_json + ", \"absoluteHumidity\":" + str(s_currAbsHum)                                                                    lacrosse_json = lacrosse_json + "}"                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/json", lacrosse_json, qos=0, retain=False)                                                                tmptext = str(s_currAvgTemp) + "° " + str(s_currAvgHum) + "%"                                mqttc.publish(mqtt_topic_prefix+"/"+ s_name +"/TempHumText", tmptext, qos=0, retain=False)                                                            if s_influxInstance is not None and storeNow:                                ### write to InfluxDB here                                                                if s_influxInstance in influxdb_yaml:                                    influx_measurement = influxdb_yaml[s_influxInstance].get('measurement', None)                                                                    t_utc = datetime.utcnow()                                    t_str = t_utc.isoformat() + 'Z'                                                                        if influx_measurement is not None:                                        influx_fieldnames = influxdb_yaml[s_influxInstance].get('fieldnames', None)                                        if influx_fieldnames == None:                                            influx_fieldname_temperature = influx_default_fieldname_temperature                                            influx_fieldname_humidity = influx_default_fieldname_humidity                                            influx_fieldname_dewpoint = influx_default_fieldname_dewpoint                                            influx_fieldname_abshum = influx_default_fieldname_abshum                                        else:                                            if influxdb_yaml[s_influxInstance]['fieldnames'].get('temperature', None) != None:                                                influx_fieldname_temperature = influxdb_yaml[s_influxInstance]['fieldnames'].get('temperature')                                            else:                                                influx_fieldname_temperature = influx_default_fieldname_temperature                                                                                        if influxdb_yaml[s_influxInstance]['fieldnames'].get('humidity', None) != None:                                                influx_fieldname_humidity = influxdb_yaml[s_influxInstance]['fieldnames'].get('humidity')                                            else:                                                influx_fieldname_humidity = influx_default_fieldname_humidity                                                                                            if influxdb_yaml[s_influxInstance]['fieldnames'].get('dewpoint', None) != None:                                                influx_fieldname_dewpoint = influxdb_yaml[s_influxInstance]['fieldnames'].get('dewpoint')                                            else:                                                influx_fieldname_dewpoint = influx_default_fieldname_dewpoint                                                                                            if influxdb_yaml[s_influxInstance]['fieldnames'].get('abshum', None) != None:                                                influx_fieldname_abshum = influxdb_yaml[s_influxInstance]['fieldnames'].get('abshum')                                            else:                                                influx_fieldname_abshum = influx_default_fieldname_abshum                                                                                        influx_datatypes = influxdb_yaml[s_influxInstance].get('datatypes', None)                                        if influx_datatypes == None:                                            influx_datatype_temperature = influx_default_datatype_temperature                                            influx_datatype_humidity = influx_default_datatype_humidity                                        else:                                            if influxdb_yaml[s_influxInstance]['datatypes'].get('temperature', None) != None:                                                tmpdt = influxdb_yaml[s_influxInstance]['datatypes'].get('temperature')                                                if tmpdt == 'float' or tmpdt == 'int':                                                    influx_datatype_temperature = tmpdt                                                else:                                                    influx_datatype_temperature = influx_default_datatype_temperature                                            else:                                                influx_datatype_temperature = influx_default_datatype_temperature                                                                                        if influxdb_yaml[s_influxInstance]['datatypes'].get('humidity', None) != None:                                                tmpdt = influxdb_yaml[s_influxInstance]['datatypes'].get('humidity')                                                if tmpdt == 'float' or tmpdt == 'int':                                                    influx_datatype_humidity = tmpdt                                                else:                                                    influx_datatype_humidity = influx_default_datatype_humidity                                            else:                                                influx_datatype_humidity = influx_default_datatype_humidity                                                                                            if influxdb_yaml[s_influxInstance]['datatypes'].get('dewpoint', None) != None:                                                tmpdt = influxdb_yaml[s_influxInstance]['datatypes'].get('dewpoint')                                                if tmpdt == 'float' or tmpdt == 'int':                                                    influx_datatype_dewpoint = tmpdt                                                else:                                                    influx_datatype_dewpoint = influx_default_datatype_dewpoint                                            else:                                                influx_datatype_dewpoint = influx_default_datatype_dewpoint                                                                                            if influxdb_yaml[s_influxInstance]['datatypes'].get('abshum', None) != None:                                                tmpdt = influxdb_yaml[s_influxInstance]['datatypes'].get('abshum')                                                if tmpdt == 'float' or tmpdt == 'int':                                                    influx_datatype_abshum = tmpdt                                                else:                                                    influx_datatype_abshum = influx_default_datatype_abshum                                            else:                                                influx_datatype_abshum = influx_default_datatype_abshum                                                                                        if influx_datatype_temperature == 'int':                                            influx_value_temp = int(s_currAvgTemp)                                        else:                                            influx_value_temp = float(s_currAvgTemp)                                                                                if influx_datatype_humidity == 'int':                                            influx_value_hum = int(s_currAvgHum)                                        else:                                            influx_value_hum = float(s_currAvgHum)                                                                                if config['sensors'].getboolean('calculate_dewpoint', False) and config['sensors'].getboolean('write_dewpoint_to_influxdb', False):                                            if influx_datatype_dewpoint == 'int':                                                influx_value_dewpoint = int(s_currDewpoint)                                            else:                                                influx_value_dewpoint = float(s_currDewpoint)                                                                                if config['sensors'].getboolean('calculate_absolute_humidity', False) and config['sensors'].getboolean('write_abshum_to_influxdb', False):                                            if influx_datatype_abshum == 'int':                                                influx_value_abshum = int(s_currAbsHum)                                            else:                                                influx_value_abshum = float(s_currAbsHum)                                                                                influx_json = [                                            {                                                'measurement': influx_measurement,                                                'tags': {                                                    'sensor': s_name                                                },                                                'time': t_str,                                                'fields': {                                                    influx_fieldname_temperature: influx_value_temp,                                                    influx_fieldname_humidity: influx_value_hum                                                }                                            }                                        ]                                                                                if config['sensors'].getboolean('calculate_dewpoint', False) and config['sensors'].getboolean('write_dewpoint_to_influxdb', False):                                            influx_json[0]["fields"][influx_fieldname_dewpoint] = influx_value_dewpoint                                                                                    if config['sensors'].getboolean('calculate_absolute_humidity', False) and config['sensors'].getboolean('write_abshum_to_influxdb', False):                                            influx_json[0]["fields"][influx_fieldname_abshum] = influx_value_abshum                                                                                                                        try:                                            if verbosemode:                                                 print("write to InfluxDB...")                                                print(influx_json)                                            influxclient[s_influxInstance].write_points(influx_json)                                            if verbosemode: print("DONE!")                                        except Exception as e:                                            print("Error writing to InfluxDB")                                            print(influx_json)                                            print(e)                                else:                                     if verbosemode:                                        print("Error: invalid InfluxDB instance '" + s_influxInstance + "' configured for sensor '" + s_name + "'")                                                                                    else: # this is an unknown sensor                            if publishNow:                                if s_battNew:                                    if config['mqtt'].getboolean('publish_unknown_new_sensors'):                                        mqttc.publish(mqtt_topic_prefix+"/NewUnknownSensor/"+str(id)+"/temperature", str(s_currAvgTemp), qos=0, retain=False)                                        mqttc.publish(mqtt_topic_prefix+"/NewUnknownSensor/"+str(id)+"/humidity", str(s_currAvgHum), qos=0, retain=False)                                        mqttc.publish(mqtt_topic_prefix+"/NewUnknownSensor/"+str(id)+"/batteryNew", s_battNew_str, qos=0, retain=False)                                else:                                    if config['mqtt'].getboolean('publish_unknown_sensors'):                                        mqttc.publish(mqtt_topic_prefix+"/UnknownSensor/"+str(id)+"/temperature", str(s_currAvgTemp), qos=0, retain=False)                                        mqttc.publish(mqtt_topic_prefix+"/UnknownSensor/"+str(id)+"/humidity", str(s_currAvgHum), qos=0, retain=False)                                        mqttc.publish(mqtt_topic_prefix+"/UnknownSensor/"+str(id)+"/battery", s_battState, qos=0, retain=False)                    if verbosemode: print()                # outside sensors        if (int(time.time()) - outSens_lastRun) > int(config['sensors'].get('publish_interval_outside', 60)):            outSens_lastRun = int(time.time())                        sum_out_sensors_temp = 0            sum_out_sensors_temp_min = 100            sum_out_sensors_temp_max = -50            sum_out_sensors_hum = 0            sum_out_sensors_hum_min = 100            sum_out_sensors_hum_max = -50            count_used_out_sensors = 0                        # "declare" variables with invalid high values - will be overwritten later            out_temp_publishvalue = 200            out_hum_publishvalue = 200            out_dewpoint = 200            out_abshum = 200                        # median            if(config['sensors'].getboolean('outside_sensors_use_median')):                out_sensors_temp_median_values = []                out_sensors_hum_median_values = []                        for id in sensors_outside_sensors:                lupd = sensors_lastUpdate.get(id, None)                tdiff = 0                if lupd is not None:                    tdiff = int(time.time()) - lupd                                    if lupd is not None and (tdiff < sensordata_maxage):                    tmpval_t = sensors_lastAvgValue_temp.get(id, None)                    tmpval_h = sensors_lastAvgValue_hum.get(id, None)                    if tmpval_t is not None and tmpval_h is not None:                        sum_out_sensors_temp = sum_out_sensors_temp + tmpval_t                        sum_out_sensors_hum = sum_out_sensors_hum + tmpval_h                                                if tmpval_t < sum_out_sensors_temp_min:                            sum_out_sensors_temp_min = tmpval_t                        if tmpval_t < sum_out_sensors_hum_min:                            sum_out_sensors_hum_min = tmpval_h                                                if tmpval_t > sum_out_sensors_temp_max:                            sum_out_sensors_temp_max = tmpval_t                        if tmpval_t > sum_out_sensors_hum_max:                            sum_out_sensors_hum_max = tmpval_h                                                                        # median                        if(config['sensors'].getboolean('outside_sensors_use_median')):                            out_sensors_temp_median_values.append(tmpval_t)                            out_sensors_hum_median_values.append(tmpval_h)                                                count_used_out_sensors += 1                        lacrosse_json = None                        if count_used_out_sensors > 0:                out_temp_avg = round((sum_out_sensors_temp / count_used_out_sensors), 1)                out_hum_avg = int(round((sum_out_sensors_hum / count_used_out_sensors), 0))                                                if(config['sensors'].getboolean('outside_sensors_use_median')):                    # median                    out_temp_median = round(statistics.median(out_sensors_temp_median_values), 1)                    out_hum_median = int(round(statistics.median(out_sensors_hum_median_values), 0))                    out_temp_publishvalue = out_temp_median                    out_hum_publishvalue = out_hum_median                                    else:                    out_temp_publishvalue = out_temp_avg                    out_hum_publishvalue = out_hum_avg                                    # calc dewpoint                if config['sensors'].getboolean('calculate_dewpoint', False):                    out_dewpoint = round(dewpoint(out_temp_avg, out_hum_avg), 1)                                # calc absolute humidity                if config['sensors'].getboolean('calculate_absolute_humidity', False):                    out_abshum = round(absoluteHumidity(out_hum_avg, out_temp_avg), 2)                                                        mqttc.publish(mqtt_topic_atemp, str(out_temp_publishvalue), qos=0, retain=True)                mqttc.publish(mqtt_topic_ahum, str(out_hum_publishvalue), qos=0, retain=True)                mqttc.publish(topic_prefix_outside_temphum + '/temperature', str(out_temp_publishvalue), qos=0, retain=True)                mqttc.publish(topic_prefix_outside_temphum + '/humidity', str(out_hum_publishvalue), qos=0, retain=True)                                if config['sensors'].getboolean('calculate_dewpoint', False):                    mqttc.publish(topic_prefix_outside_temphum + '/dewpoint', str(out_dewpoint), qos=0, retain=True)                                    if config['sensors'].getboolean('calculate_absolute_humidity', False):                    mqttc.publish(topic_prefix_outside_temphum + '/absoluteHumidity', str(out_abshum), qos=0, retain=True)                                mqttc.publish(topic_prefix_outside_temphum + '/temp_average', str(out_temp_avg), qos=0, retain=True)                mqttc.publish(topic_prefix_outside_temphum + '/hum_average', str(out_hum_avg), qos=0, retain=True)                                if(config['sensors'].getboolean('outside_sensors_use_median')):                    mqttc.publish(topic_prefix_outside_temphum + '/temp_median', str(out_temp_median), qos=0, retain=True)                    mqttc.publish(topic_prefix_outside_temphum + '/hum_median', str(out_hum_median), qos=0, retain=True)                                    mqttc.publish(topic_prefix_outside_temphum + '/lastUpdate', strftime("%Y-%m-%d %H:%M:%S", localtime()), qos=0, retain=True)                                                                tmptext = str(out_temp_publishvalue) + "° " + str(out_hum_publishvalue) + "%"                mqttc.publish(topic_prefix_outside_temphum + "/TempHumText", tmptext, qos=0, retain=False)                            lacrosse_json = "{\"temperature\":" + str(out_temp_publishvalue) + \                                ", \"humidity\":" + str(out_hum_publishvalue) + "\"" \                                ", \"usedSensors\":" + str(count_used_out_sensors)                        min = 100            max = 100            if count_used_out_sensors > 1:                mqttc.publish(topic_prefix_outside_temphum + '/usedSensors', str(count_used_out_sensors), qos=0, retain=True)                                lacrosse_json = lacrosse_json + \                                ", \"temp_average\":" + str(out_temp_avg) + \                                ", \"hum_average\":" + str(out_hum_avg) + \                                ", \"temp_median\":" + str(out_temp_median) + \                                ", \"hum_median\":" + str(out_temp_median)                                if sum_out_sensors_temp_min < 100:                    mqttc.publish(topic_prefix_outside_temphum + '/temp_min', str(sum_out_sensors_temp_min), qos=0, retain=False)                    lacrosse_json = lacrosse_json + ", \"temp_min\":" + str(sum_out_sensors_temp_min)                if sum_out_sensors_temp_max > -50:                    mqttc.publish(topic_prefix_outside_temphum + '/temp_max', str(sum_out_sensors_temp_max), qos=0, retain=False)                    lacrosse_json = lacrosse_json + ", \"temp_max\":" + str(sum_out_sensors_temp_max)                if sum_out_sensors_hum_min < 100:                    mqttc.publish(topic_prefix_outside_temphum + '/hum_min', str(sum_out_sensors_hum_min), qos=0, retain=False)                    lacrosse_json = lacrosse_json + ", \"hum_min\":" + str(sum_out_sensors_hum_min)                if sum_out_sensors_hum_max > -50:                    mqttc.publish(topic_prefix_outside_temphum + '/hum_max', str(sum_out_sensors_hum_max), qos=0, retain=False)                    lacrosse_json = lacrosse_json + ", \"hum_max\":" + str(sum_out_sensors_hum_max)                                            if lacrosse_json is not None:                if config['sensors'].getboolean('calculate_dewpoint', False):                    lacrosse_json = lacrosse_json + ", \"dewpoint\":" + str(out_dewpoint)                if config['sensors'].getboolean('calculate_absolute_humidity', False):                    lacrosse_json = lacrosse_json + ", \"absoluteHumidity\":" + str(out_abshum)                                    lacrosse_json = lacrosse_json + "}"                mqttc.publish(topic_prefix_outside_temphum + "/json", lacrosse_json, qos=0, retain=False)                                                            # combined outside sensors to InfluxDB                        o_hasValidData = False            if out_temp_publishvalue < 200 and out_hum_publishvalue < 200:                o_hasValidData = True                        o_storeNow = False            if (int(time.time()) - outSens_store_lastRun) > int(config['sensors'].get('store_interval_outside', 300)):                if outSens_store_lastRun == 0:                    outSens_store_lastRun = int(time.time())                else:                    o_storeNow = True                    outSens_store_lastRun = int(time.time())                        if o_storeNow and o_hasValidData:                outSens_store_lastRun = int(time.time())                o_influxInstance = config['sensors'].get('influxdb_instance_combined_outside_sensors')                o_influxSensorName = config['sensors'].get('influxdb_sensorname_combined_outside_sensors', None)                if o_influxInstance in influxdb_yaml and o_influxSensorName is not None:                    influx_measurement = influxdb_yaml[o_influxInstance].get('measurement', None)                                        t_utc = datetime.utcnow()                    t_str = t_utc.isoformat() + 'Z'                                        if influx_measurement is not None:                        influx_fieldnames = influxdb_yaml[o_influxInstance].get('fieldnames', None)                        if influx_fieldnames == None:                            influx_fieldname_temperature = influx_default_fieldname_temperature                            influx_fieldname_humidity = influx_default_fieldname_humidity                            influx_fieldname_dewpoint = influx_default_fieldname_dewpoint                            influx_fieldname_abshum = influx_default_fieldname_abshum                        else:                            if influxdb_yaml[o_influxInstance]['fieldnames'].get('temperature', None) != None:                                influx_fieldname_temperature = influxdb_yaml[o_influxInstance]['fieldnames'].get('temperature')                            else:                                influx_fieldname_temperature = influx_default_fieldname_temperature                                                        if influxdb_yaml[o_influxInstance]['fieldnames'].get('humidity', None) != None:                                influx_fieldname_humidity = influxdb_yaml[o_influxInstance]['fieldnames'].get('humidity')                            else:                                influx_fieldname_humidity = influx_default_fieldname_humidity                                                            if influxdb_yaml[o_influxInstance]['fieldnames'].get('dewpoint', None) != None:                                influx_fieldname_dewpoint = influxdb_yaml[o_influxInstance]['fieldnames'].get('dewpoint')                            else:                                influx_fieldname_dewpoint = influx_default_fieldname_dewpoint                                                            if influxdb_yaml[o_influxInstance]['fieldnames'].get('abshum', None) != None:                                influx_fieldname_abshum = influxdb_yaml[o_influxInstance]['fieldnames'].get('abshum')                            else:                                influx_fieldname_abshum = influx_default_fieldname_abshum                                                        influx_datatypes = influxdb_yaml[o_influxInstance].get('datatypes', None)                        if influx_datatypes == None:                            influx_datatype_temperature = influx_default_datatype_temperature                            influx_datatype_humidity = influx_default_datatype_humidity                        else:                            if influxdb_yaml[o_influxInstance]['datatypes'].get('temperature', None) != None:                                tmpdt = influxdb_yaml[o_influxInstance]['datatypes'].get('temperature')                                if tmpdt == 'float' or tmpdt == 'int':                                    influx_datatype_temperature = tmpdt                                else:                                    influx_datatype_temperature = influx_default_datatype_temperature                            else:                                influx_datatype_temperature = influx_default_datatype_temperature                                                        if influxdb_yaml[o_influxInstance]['datatypes'].get('humidity', None) != None:                                tmpdt = influxdb_yaml[o_influxInstance]['datatypes'].get('humidity')                                if tmpdt == 'float' or tmpdt == 'int':                                    influx_datatype_humidity = tmpdt                                else:                                    influx_datatype_humidity = influx_default_datatype_humidity                            else:                                influx_datatype_humidity = influx_default_datatype_humidity                                                            if influxdb_yaml[o_influxInstance]['datatypes'].get('dewpoint', None) != None:                                tmpdt = influxdb_yaml[o_influxInstance]['datatypes'].get('dewpoint')                                if tmpdt == 'float' or tmpdt == 'int':                                    influx_datatype_dewpoint = tmpdt                                else:                                    influx_datatype_dewpoint = influx_default_datatype_dewpoint                            else:                                influx_datatype_dewpoint = influx_default_datatype_dewpoint                                                            if influxdb_yaml[o_influxInstance]['datatypes'].get('abshum', None) != None:                                tmpdt = influxdb_yaml[o_influxInstance]['datatypes'].get('abshum')                                if tmpdt == 'float' or tmpdt == 'int':                                    influx_datatype_abshum = tmpdt                                else:                                    influx_datatype_abshum = influx_default_datatype_abshum                            else:                                influx_datatype_abshum = influx_default_datatype_abshum                                                        if influx_datatype_temperature == 'int':                            influx_value_temp = int(out_temp_publishvalue)                        else:                            influx_value_temp = float(out_temp_publishvalue)                                                if influx_datatype_humidity == 'int':                            influx_value_hum = int(out_hum_publishvalue)                        else:                            influx_value_hum = float(out_hum_publishvalue)                                                if config['sensors'].getboolean('calculate_dewpoint', False) and config['sensors'].getboolean('write_dewpoint_to_influxdb', False):                            if influx_datatype_dewpoint == 'int':                                influx_value_dewpoint = int(out_dewpoint)                            else:                                influx_value_dewpoint = float(out_dewpoint)                                                if config['sensors'].getboolean('calculate_absolute_humidity', False) and config['sensors'].getboolean('write_abshum_to_influxdb', False):                            if influx_datatype_abshum == 'int':                                influx_value_abshum = int(out_abshum)                            else:                                influx_value_abshum = float(out_abshum)                                                influx_json = [                            {                                'measurement': influx_measurement,                                'tags': {                                    'sensor': o_influxSensorName                                },                                'time': t_str,                                'fields': {                                    influx_fieldname_temperature: influx_value_temp,                                    influx_fieldname_humidity: influx_value_hum                                }                            }                        ]                                                if config['sensors'].getboolean('calculate_dewpoint', False) and config['sensors'].getboolean('write_dewpoint_to_influxdb', False) and out_dewpoint < 200:                            influx_json[0]["fields"][influx_fieldname_dewpoint] = influx_value_dewpoint                                                    if config['sensors'].getboolean('calculate_absolute_humidity', False) and config['sensors'].getboolean('write_abshum_to_influxdb', False) and out_abshum < 200:                            influx_json[0]["fields"][influx_fieldname_abshum] = influx_value_abshum                                                                        try:                            if verbosemode:                                 print("write to InfluxDB...")                                print(influx_json)                            influxclient[o_influxInstance].write_points(influx_json)                            if verbosemode: print("DONE!")                        except Exception as e:                            print("Error writing to InfluxDB")                            print(influx_json)                            print(e)                                # handle outdated sensor values once a minute        if (int(time.time()) - checkLastUpdateInterval_lastRun) > checkLastUpdateInterval:                    # exit program if nothing has been received from JeeLink for 5 min - will be restarted by systemd            now = int(time.time())            if (now - serialReceivedLastTime) > serialReceived_maxAge:                print("Nothing received from JeeLink for " + str(now - serialReceivedLastTime) + "s - there is something wrong. Exiting program so that it will be restarted by systemd.")                quit()                            checkLastUpdateInterval_lastRun = int(time.time())            #print("check lastUpdate")            for key in sensors_yaml:                #print(key, '->', sensors_yaml[key])                #print("Sensor name:", key)                sensorId = sensors_yaml[key].get('LaCrosseID', None)                if sensorId >= 0:                    lupd = sensors_lastUpdate.get(sensorId, None)                    tdiff = 0                    if lupd is not None:                        tdiff = int(time.time()) - lupd                                            if lupd is None or (tdiff > sensordata_maxage):                                                mqttc.publish(mqtt_topic_prefix+"/"+ key +"/availability", "unavailable", qos=0, retain=False)                        notifystr = "received no data from sensor '" + key + "' with ID " + str(sensorId) + " for " + str(tdiff) + "s"                        mqttc.publish(mqtt_topic_prefix+"/" + mqtt_subtopic_notify, notifystr, qos=0, retain=False)            except KeyboardInterrupt:    print('\n')    exit()
 |