[SOLVED] Openhab get last item state

Hi,

I’m using MySQL persitence and i would need to get last value of an item but the problem is that last state that i’m reading is actually current new state of an item.

I’m using previousState function

rule "KNX Scene"
	when
 		Item light_scene_r101_act received command
 	then
 		val light_scene_r101_old = light_scene_r101_act.previousState(false, "mysql").state as DecimalType
 		val light_scene_r101_act = receivedCommand as DecimalType
 		
 		switch(light_scene_r101_act) {
 			case 1 : {
 				logInfo("Demo", "Act = " + light_scene_r101_act)
 				logInfo("Demo", "Old = " + light_scene_r101_old)
 				if(light_scene_r101_old.toString >= "1" && light_scene_r101_old.toString < "4") {
 					sendCommand(light_scene_r000_set, "4")
 				} else {
 					sendCommand(light_scene_r000_set, "1")
 				}
 			}
 			case 2 : {
 				logInfo("Demo", "Act = " + light_scene_r101_act)
 				logInfo("Demo", "Old = " + light_scene_r101_old)
 				if(light_scene_r101_old.toString == "2") {
 					sendCommand(light_scene_r000_set, "4")
 					logInfo("Demo", "Poslji")
 				} else {
 					sendCommand(light_scene_r000_set, "2")
 					logInfo("Demo", "Poslji")
 				}
 			}
 			
 			case 3 : {
 				logInfo("Demo", "Act = " + light_scene_r101_act)
 				logInfo("Demo", "Old = " + light_scene_r101_old)
 				if(light_scene_r101_old.toString == "3") {
 					sendCommand(light_scene_r000_set, "4")
 				} else {
 					sendCommand(light_scene_r000_set, "3")
 				}
 			}
 			
 			case 4 : {
 				logInfo("Demo", "Act = " + light_scene_r101_act)
 				logInfo("Demo", "Old = " + light_scene_r101_old)
 				if(light_scene_r101_old.toString == "4") {
 					sendCommand(light_scene_r000_set, "4")
 				} else {
 					sendCommand(light_scene_r000_set, "4")
 				}
 			}
 		}

Check Java Switch Case in openhab rules.
Seems Xtend doesn’t use the switch expression like other languages (with breaks) …

Yes but the problem is that persistance happens before rule so last value in database is actually new value.

I don’t understand your rule :slight_smile:

First step: getting values and store them in a constant as a DecimalType.
After that, logging them (I guess this should end in an error, as you try to pass a DecimalType as a string)
and comparing them as a string… I’m puzzled…
Try this:

rule "KNX Scene"
when
    Item light_scene_r101_act received command
then
    val light_scene_r101_old = light_scene_r101_act.previousState(false, "mysql").state as DecimalType
    val light_scene_r101_act = receivedCommand as DecimalType
    logInfo("Demo", "Act = " + light_scene_r101_act.toString)
    logInfo("Demo", "Old = " + light_scene_r101_old.toString)
    switch(light_scene_r101_act) {
        case 1 : {
            if(light_scene_r101_old >= 1 && light_scene_r101_old < 4) {
                light_scene_r000_set.sendCommand(4)
            }
            else {
                light_scene_r000_set.sendCommand(1)
            }
        }
        case 2 : {
            logInfo("Demo", "Poslji")
            if(light_scene_r101_old == 2) {
                light_scene_r000_set.sendCommand(4)
            }
            else {
                light_scene_r000_set.sendCommand(2)
            }
        }
        case 3 : {
            if(light_scene_r101_old == 3) {
                light_scene_r000_set.sendCommand(4)
            }
            else {
                light_scene_r000_set.sendCommand(3)
            }
        }
        case 4 : {
            sendCommand(light_scene_r000_set, "4")
        }
    }
end

And I guess this would be easier:

rule "KNX Scene"
when
    Item light_scene_r101_act received command
then
    val Int light_scene_r101_old = light_scene_r101_act.previousState(false, "mysql").state as DecimalType
    val Int light_scene_r101_act = receivedCommand as DecimalType
    logInfo("Demo", "Act = " + light_scene_r101_act.toString)
    logInfo("Demo", "Old = " + light_scene_r101_old.toString)
    if(light_scene_r101_act == 2) {
        logInfo("Demo", "Poslji")
    }
    if(light_scene_r101_act == light_scene_r101_old) {
        light_scene_r000_set.sendCommand(4)
    }
    else {
        light_scene_r000_set.sendCommand(light_scene_r101_act)
    }
end

If you use previousState(true, “mysql”) it will return the most recent previous state that is different from the current state. It is possible that your Item is receiving more than one event or command and unless you have your persistence set up to only save changes that will mean that you will get multiple entries in the DB. Using the “true” will help filter that out.

1 Like

Here I am again with fixed rule and fixed problem.

I have a KNX light switch witch is switching between scenes.
Example: If you press button 2 and previous state was something else then it sends 2 to knx address but if switch state was already 2 then it will switch it to 4 whics means OFF.

Items:

Number item_light_scene_r101_act "Branje scene" {autoupdate="true", knx="5.005:1/4/1" }
Number item_light_scene_r101_act_old "Stara vrednost"
Number item_light_scene_r000_set "Vpisovanje scene" {autoupdate="true", knx="5.005:1/4/0" }

Rules:

rule "KNX Scene"
	when
 		Item item_light_scene_r101_act received command
 	then
 		val light_scene_r101_act_old = item_light_scene_r101_act_old.state
 		val light_scene_r101_act = receivedCommand as DecimalType
 			
 		switch(light_scene_r101_act) {
 			case 1 : {
 				if(light_scene_r101_act_old >= 1 && light_scene_r101_act_old < 4) {
 					sendCommand(item_light_scene_r000_set, 4)
 					sendCommand(item_light_scene_r101_act_old, 4) // Začasno
 				} else {
 					sendCommand(item_light_scene_r000_set, 1)
 					sendCommand(item_light_scene_r101_act_old, 1) // Začasno
 				}
 			}
 			case 2 : {
 				if(light_scene_r101_act_old == 2) {
 					sendCommand(item_light_scene_r000_set, 4)
 					sendCommand(item_light_scene_r101_act_old, 4) // Začasno
 				} else {
 					sendCommand(item_light_scene_r000_set, 2)
 					sendCommand(item_light_scene_r101_act_old, 2) // Začasno
 				}
 			}
 			
 			case 3 : {
 				if(light_scene_r101_act_old == 3) {
 					sendCommand(item_light_scene_r000_set, 4)
 					sendCommand(item_light_scene_r101_act_old, 4) // Začasno
 				} else {
 					sendCommand(item_light_scene_r000_set, 3)
 					sendCommand(item_light_scene_r101_act_old, 3) // Začasno
 				}
 			}
 			
 			case 4 : {
 				if(light_scene_r101_act_old == 4) {
 					sendCommand(item_light_scene_r000_set, 4)
 					sendCommand(item_light_scene_r101_act_old, 4) // Začasno
 				} else {
 					sendCommand(item_light_scene_r000_set, 4)
 					sendCommand(item_light_scene_r101_act_old, 4) // Začasno
 				}
 			}
 		}

	end

I’m also using MapDB now because it only store last value which is exactly what i need.

Or a little bit shorter :wink:

rule "KNX Scene"
when
    Item light_scene_r101_act received command
then
    val Int iOld = light_scene_r101_act_old.state as DecimalType
    val Int iNew = receivedCommand as DecimalType
    if(iNew == iOld) {
        light_scene_r000_set.sendCommand(4)
    }
    else {
        light_scene_r000_set.sendCommand(iNew)
    }
    light_scene_r101_act_old.sendCommand(light_scene_r000_set.state)
end
2 Likes