Browse Source

BUGFIX: check correct size of incoming data and prevent crash if invalid

FloKra 2 years ago
parent
commit
a08c672863
1 changed files with 189 additions and 181 deletions
  1. 189 181
      jeelinklog/jeelinklog.py

+ 189 - 181
jeelinklog/jeelinklog.py

@@ -246,7 +246,7 @@ try:
         try: 
             serLine = serLine.decode('ascii')
         except:
-            serLine = ""
+            serLine = False
 
         if(serLine):
             if serLine.find('OK 9') != -1:
@@ -268,204 +268,212 @@ try:
                 
                 serLineParts = serLine.split(' ')
                 
-                #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)
+                #print("Len: " + str(len(serLineParts)))
                 
-                if sensors_lastValues_temp.get(addr, None) == None:
-                    sensors_lastValues_temp[addr] = [None] * average_value_steps
+                if(len(serLineParts) == 7): # check correct size of incoming data
                 
-                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)
+                    #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]))
+                        
                     
-                    max_off_value = float(config['sensors'].get('max_off_value'))
-                    ignore_off_value_timeout = int(config['sensors'].get('ignore_off_value_timeout'))
+                    lastUpdate = sensors_lastUpdate.get(addr, None)
+                    lastTemp = sensors_lastTemp.get(addr, None)
+                    lastHum = sensors_lastHum.get(addr, None)
                     
-                    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
+                    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:
-                        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
+                        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:
-                        lastValues_lastIndex += 1
-                    if verbosemode: print("lastValues_lastIndex =", lastValues_lastIndex)
+                        batt_low = 0
+                        hum = int(serLineParts[6])
+                        if hum > 100: 
+                            hum = 100
                     
-                    sensors_lastValues_lastIndex[addr] = lastValues_lastIndex
-                    sensors_lastValues_temp[addr][lastValues_lastIndex] = temp
-                    sensors_lastValues_hum[addr][lastValues_lastIndex] = hum
+                    if batt_new == 1:
+                        sensors_batteryState[addr] = 2
+                    elif batt_low == 1:
+                        sensors_batteryState[addr] = 1
+                    else:
+                        sensors_batteryState[addr] = 0
                     
-                    sensors_lastUpdate[addr] = int(time.time())
+                    lastValues_lastIndex = sensors_lastValues_lastIndex.get(addr, None)
                     
-                    if verbosemode: print("sensors_lastValues_temp =", sensors_lastValues_temp[addr])
+                    if sensors_lastValues_temp.get(addr, None) == None:
+                        sensors_lastValues_temp[addr] = [None] * average_value_steps
                     
-                
-                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 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)
                         
-                        if not os.path.exists(log_path+'/new'):
-                            os.makedirs(log_path+'/new')
+                        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)
                             
-                        fname = log_path + '/new/' + str(addr)
-                        if not os.path.exists(fname):
-                            try:
-                                touch(fname)
-                            except:
-                                pass
+                    
+                    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())
                         
-                        try:
-                            f = open(log_path+'/'+logfile_new_sensors, 'a')
-                            f.write(str(datetime.now())+": "+notifystr+"\n")
-                            f.close()
-                        except:
-                            # guat dann hoit ned...
-                            pass
+                        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
                             
-                        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)
+                                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("unknown sensor ID " + str(addr))
-                                    
-                if verbosemode:
-                    print("addr: " + str(addr) + " = 0x" + str(addrhex) + "   batt_new: " + str(batt_new) + "   type: " + str(type) + "   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")
+                        print("addr: " + str(addr) + " = 0x" + str(addrhex) + "   batt_new: " + str(batt_new) + "   type: " + str(type) + "   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("ignored invalid sized data")
+                    pass
         
         
         # publish on MQTT on set interval