[SOLVED] Persisting (and graphing) Lock Status

Hi all,
I am looking to better persist my lock data so that I can graph the lock status, making it obvious when the door was unlocked and when it was locked. I am using schlage connect BE469 z-wave locks to a OH 2.4 stable with latest zwave snapshot, on a RPi 3B.

While my default persistence is mapdb for everything/restore purposes, I also have influxdb running, which supplies the data to graphana. My influxdb.persist file initially had specified every 15 minutes as well as every change, but given the null values being (apparently) populated, I changed it to just everyChange.
**
Question: Is there a way - either in fixing the persistence, creating rules to maintain the ‘1’ status of a locked door, or in grafana, to graph a solid ‘1’ for the entire time the door is locked, going down to ‘0’ when it is unlocked and staying there while unlocked? Hopefully the picture below will illustrate what I currently have (graph and table of values). If the graph were working correctly it may be quite crowded with all the locks on it, but I kept them all in there for additional information for this.

My grafana settings:


(of note, the graph is the same with either last or mean as the method of aggregating data.

my influxdb.persist

Strategies {
everyMinute : "0 * * * * ?"
everyHour : "0 0 * * * ?"
everyDay : "0 0 0 * * ?"
every2Minutes : "0 */2 * ? * *"
every5Minutes : "0 */5 * ? * *"
every15Minutes : "0 */15 * ? * *"
default = everyChange
}

Items {
gTemperatureItems*: strategy = everyHour, everyChange
gHumidityItems*: strategy = everyHour, everyChange
gMotionItems*: strategy = every15Minutes, everyChange
gAnyRecentMotion*: strategy = every15Minutes, everyChange
gLightSensorItems*: strategy = everyHour, everyChange
gWeatherTemp*, gWeatherHumidity*: strategy = everyHour
Presence_Sensors*: strategy = every15Minutes, everyChange
gLock*: strategy = everyChange
}

All the locks are members of the gLock group

locks.rules

rule "Lock: Update lock states after alarm_raw event"
when
    Member of gLockRaw received update
then
    val actionItem = gLock.members.findFirst[ item | item.name.toString == triggeringItem.name.toString.replace("_Alarm_Raw","") ]
	logInfo("locks.rules", "Starting Lock Update Raw Event Rule")
    logInfo("Rules", "Lock: Alarm events: {}=[{}]",actionItem.name,triggeringItem.state.toString)
	
	// Event 1 = Manual Lock ; Event 2 = Manual Unlock; Event 3 =  ?locked with ZWave ; Event 4 = ?Unlocked with zwave; Event 5 = Keypad Lock; Event 6 = Keypad Unlock; Event 7-10 = ?; Event 11 = Jammed Lock; Event 12-15 = ?; Event 16 = Keypad disabled from too many wrong codes
	
	var Boolean mailNotify=false
    switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
        case "ACCESS_CONTROL" : {
            switch (transform("JSONPATH", "$.event", triggeringItem.state.toString)) {
                case "1" : {
                    actionItem.postUpdate(ON)
                    logInfo("Rules", "Lock: Alarm events: {} updated to ON (manually locked)",actionItem.name)
                }
                case "2" : {
                    actionItem.postUpdate(OFF)
                    logInfo("Rules", "Lock: Alarm events: {} updated to OFF (manually unlocked)",actionItem.name)
                }
				
				// ?Locked with zwave.  There doesn't seem to be any actual event sent out from the lock, based on the logs, though.
				case "3" : {
					actionItem.postUpdate(ON)
					logInfo("Rules", "Lock: Alarm events: {} updated to ON (Locked, Event code 3, possibly locked with Z-Wave)",actionItem.name)
				}
				
				// ?Unlocked with zwave.  There doesn't seem to be any actual event sent out from the lock, based on the logs, though.
				case "4" : {
                    actionItem.postUpdate(OFF)
                    logInfo("Rules", "Lock: Alarm events: {} updated to OFF (Unlocked, Event code 4, possibly unlocked with Z-Wave)",actionItem.name)
                }
				
				// Locked by keypad
				case "5" : { 
                    actionItem.postUpdate(ON)
                    logInfo("Rules", "Lock: Alarm events: {} updated to ON (locked by keypad)",actionItem.name)
                } 
				
				// Unlocked by keypad
                case "6" : {
                    actionItem.postUpdate(OFF)
                    val StringBuilder message = new StringBuilder(actionItem.name)
					val StringBuilder messageSubject = new StringBuilder(actionItem.name)
					messageSubject.append(" unlocked by code ")
                    message.append(" was unlocked by keypad with")
                    switch (transform("JSONPATH", "$.code", triggeringItem.state.toString)) {
                        case "1" : {
                            message.append(" user code 1")
							messageSubject.append("1")
                        }
                        case "2" : {
                            message.append(" user code 2")
							messageSubject.append("2")
                        }
						case "3" : {
                            message.append(" user code 3")
							messageSubject.append("3")
                        }
						case "4" : {
                            message.append(" user code 4")
							messageSubject.append("4")
                        }
						case "5" : {
						    messageSubject.insert(0,"Guest Unlock - ")
							messageSubject.append("5")
                            message.append(" user code 5 - GUEST CODE")
							mailNotify=true

                        }
						case "6" : {
                            messageSubject.insert(0,"Cleaner Unlock - ")
							message.append(" user code 6")
							messageSubject.append("6")
							mailNotify=true
                        }
						case "7" : {
                            message.append(" user code 7")
							messageSubject.append("7")
                        }
						case "8" : {
                            message.append(" user code 8")
							messageSubject.append("8")
                        }
						case "9" : {
                            message.append(" user code 9")
							messageSubject.append("9")
                        }
						case "10" : {
                            message.append(" user code 10")
							messageSubject.append("10")
                        }
                    }
					message.append(".  Device Name: ")
					message.append(actionItem.name)
                    logInfo("Rules", "Lock: {}",message.toString)
					
// for cases where notification is pertinent, email notify (ie guest code used, cleaner code used)
					if (mailNotify) {
					  message.append(" (confirmed)")
					  sendMail("xxxxx@yyyyy.com", messageSubject.toString, message.toString)
					}

                }
                case "11" : {
                    logInfo("Rules", "Lock: Alarm events: {} is jammed, so setting lock to OFF (unlocked)",actionItem.label)
                    actionItem.postUpdate(OFF)
                    //SMS_Notification.sendCommand(actionItem.label + " is jammed")
                    //Kodi_Notification.sendCommand(actionItem.label + " is jammed")
                }
                case "16" : {
                    val String message = actionItem.label + " keypad is disabled due to too many failed codes"
                    logInfo("Rules", "Lock: Alarm events: {}",message)
					sendMail("xxxxxxxxx@yyyyyyyy.com", "Lock Keypad Disabled - too many failed codes", message.toString)
                    //SMS_Notification.sendCommand(message)
                    //Kodi_Notification.sendCommand(message)
                }
                default : {
                    val String message = "Unknown door lock Event, " + triggeringItem.state.toString
                    logInfo("Rules", "Lock: Alarm events: {}",message)
                    //SMS_Notification.sendCommand(message)
                }
            }
//            if (transform("JSONPATH", "$.event", triggeringItem.previousState(true).state.toString) == "11" && transform("JSONPATH", "$.event", triggeringItem.state.toString) != "11") {
 //               val String message = actionItem.label + " is no longer jammed"
  //              logInfo("Rules", "Lock: Alarm events: {}",message)
  //              //SMS_Notification.sendCommand(message)
  //              //Kodi_Notification.sendCommand(message)
  //          }
        }
        case "BURGLAR" : {
            //gSiren.sendCommand(ON)
            val String message = "Intruder at " + actionItem.label
            logInfo("Rules", "Lock: Alarm events: {}",message)
			sendMail("111111111111@msg.provider.com", "Burglar Alarm", message)
			sendMail("xxxxxxxxx@yyyyyyyy.com", "Burglar Alarm", message)
            //SMS_Notification.sendCommand(message)
            //Audio_Notification.sendCommand(message)
        }
        case "POWER_MANAGEMENT" : {
            val String message = "Power Management alarm for " + actionItem.label + ", " + triggeringItem.state.toString
            logInfo("Rules", "Lock: Alarm events: {}",message)
			sendMail("xxxxxxxxx@yyyyyyyy.com", "Lock Power Alarm", message)
		
            //SMS_Notification.sendCommand(message)
        }
        default : {
            val String message = "Unknown Type in alarmRawParser, " + triggeringItem.state.toString
            logInfo("Rules", "Lock: Alarm events: {}",message)
            //SMS_Notification.sendCommand(message)
        }
    }
    /*
        {"notification":"ACCESS__MANUAL_LOCK",                          "type":"ACCESS_CONTROL","event":"1","status":"255"}
        {"notification":"ACCESS__MANUAL_UNLOCK",                        "type":"ACCESS_CONTROL","event":"2","status":"255"}
        unlocked with zwave? event 3
        locked with zwave? event 4
        {"notification":"ACCESS__KEYPAD_LOCK",  "code":"1",             "type":"ACCESS_CONTROL","event":"5","status":"255"}
        {"notification":"ACCESS__KEYPAD_UNLOCK","code":"1",             "type":"ACCESS_CONTROL","event":"6","status":"255"}
        {"notification":"ACCESS__LOCK_JAMMED",                          "type":"ACCESS_CONTROL","event":"11","status":"255"}
        {"notification":"ACCESS__KEYPAD_LOCK",                          "type":"ACCESS_CONTROL","event":"5","status":"255"}
        {"notification":"ACCESS_CONTROL__KEYPAD_TEMPORARILY_DISABLED",  "type":"ACCESS_CONTROL","event":"16","status":"255"}
        {"notification":"BURGLAR__TAMPER_UNKNOWN",                      "type":"BURGLAR","event":"2","status":"255"}
        {"notification":"HOME_SECURITY__INTRUSION_UNKNOWN",             "type":"BURGLAR","event":"2","status":"255"}
        {"notification":"POWER__REPLACE_BATTERY_SOON",                  "type":"POWER_MANAGEMENT","event":"10","status":"255"}
        {"notification":"POWER_MANAGEMENT__REPLACE_BATTERY_SOON",       "type":"POWER_MANAGEMENT","event":"10","status":"255"}
    */
	
	
	/*
	FF_MasterBedroom_Lock_Alarm_Raw changed from {"notification":"ACCESS_CONTROL__MANUAL_UNLOCK","level":"1","type":"ACCESS_CONTROL","event":"2","status":"255"} to {"notification":"ACCESS_CONTROL__KEYPAD_LOCK","level":"0","type":"ACCESS_CONTROL","event":"5","status":"255"}
	*/
end

[of note, my previous schlage/zwave/persistence error was related to section in the rule for previously jammed locks, and commenting out this section fixed my error : Link to post

Thanks,

Ben

Here is your problem:
image
Chose field(value) distinct() instead of mean()

Thanks! That was it exactly.