Selfish request: Code review

  • Platform information:
    • Hardware: x64 core i7, 16GB RAM, 1TB SSD
    • OS: Ubuntu 20.04 headless server
    • Java Runtime Environment: Zulu 11
    • openHAB version: 3.1.0
  • Issue of the topic: I’m keen to learn more efficient and better ways to use openHAB, I have a working rule and am interested in if the actions that dim the light for a ‘night light’ can be scripted (it’s all current in a rule).
  • Please post configurations (if applicable):
    • Items configuration related to the issue: Philips Hue lights
    • Sitemap configuration related to the issue: Haven’t started figuring out how to do sitemaps yet
    • Rules code related to the issue: DSL
    • Services configuration related to the issue: umm…unsure.
  • If logs where generated please post these here using code fences: Don’t really need to because there are no errors and the log messages are being posted OK.

Current rule:

var Timer motionTimer2 = null

rule "Lounge Room Motionsensor"

when
    Item Huemotionsensor2_Motion changed
then
    try {
	if(now.getHour > 5) {
		if(now.getHour > 20) {
			if(Lampbulb1nexttofire_Brightness.state == 0) {
				logInfo("LoungeRoomMotiontimer", "Motion Detected during night, night light started")
				LampBulb2nexttofire_Color.sendCommand("5,90,5")
				LampBulb2nexttofire_Color.sendCommand("ON")
				Lampbulb1nexttofire_Brightness.sendCommand("5")
				Lampbulb1nexttofire_Color_Temperature.sendCommand("90")
				Lampbulb1nexttofire.sendCommand("ON")
				motionTimer2 = createTimer(now.plusSeconds(30), [ |
					LampBulb2nexttofire_Color.sendCommand("OFF")
					Lampbulb1nexttofire.sendCommand("OFF")
       				])
			} else {
				logInfo("LoungeRoomMotiontimer", "Motion Detected during night, the light was already on")
			}
		} else {
			logInfo("LoungeRoomMotiontimer", "Motion Detected during day, no night light needed")
		}
	} else {
		if(Lampbulb1nexttofire_Brightness.state == 0) {
			logInfo("LoungeRoomMotiontimer", "Motion Detected during night, night light started")
			LampBulb2nexttofire_Color.sendCommand("5,90,5")
			LampBulb2nexttofire_Color.sendCommand("ON")
			Lampbulb1nexttofire_Brightness.sendCommand("5")
			Lampbulb1nexttofire_Color_Temperature.sendCommand("90")
			Lampbulb1nexttofire.sendCommand("ON")
			motionTimer2 = createTimer(now.plusSeconds(30), [ |
				LampBulb2nexttofire_Color.sendCommand("OFF")
				Lampbulb1nexttofire.sendCommand("OFF")
       			])
		} else {
			logInfo("LoungeRoomMotiontimer", "Motion Detected during night, the light was already on")
		}
	}	
    } catch(Throwable t) {
	logError("LoungeRoomMotiontimer", "Motion Detection error in the Lounge Room: " + t.toString)
    } finally {
    }
end

It looks like you want the motion sensor to turn on the light only if it’s before 5:00 or after 20:00, right? Since the code at both places are exactly the same you could combine the conditions:

var Timer motionTimer2 = null

rule "Lounge Room Motionsensor"

when
    Item Huemotionsensor2_Motion changed
then
    try {
	if(now.getHour < 5 || now.getHour > 20) {
			if(Lampbulb1nexttofire_Brightness.state == 0) {
				logInfo("LoungeRoomMotiontimer", "Motion Detected during night, night light started")
				LampBulb2nexttofire_Color.sendCommand("5,90,5")
				LampBulb2nexttofire_Color.sendCommand("ON")
				Lampbulb1nexttofire_Brightness.sendCommand("5")
				Lampbulb1nexttofire_Color_Temperature.sendCommand("90")
				Lampbulb1nexttofire.sendCommand("ON")
				motionTimer2 = createTimer(now.plusSeconds(30), [ |
					LampBulb2nexttofire_Color.sendCommand("OFF")
					Lampbulb1nexttofire.sendCommand("OFF")
       				])
			} else {
				logInfo("LoungeRoomMotiontimer", "Motion Detected during night, the light was already on")
		} else {
			logInfo("LoungeRoomMotiontimer", "Motion Detected during day, no night light needed")
		}
	}	
    } catch(Throwable t) {
	logError("LoungeRoomMotiontimer", "Motion Detection error in the Lounge Room: " + t.toString)
    } finally {
    }
end

Also, I wouldn’t expect this code to throw any errors, so the try-catch block is not needed. If there would be an error, the only thing that happens is that the rule don’t execute properly and you will get an error in the log, but it will still run the next time it’s triggered.

var Timer motionTimer2 = null

rule "Lounge Room Motionsensor"

when
    Item Huemotionsensor2_Motion changed
then
	if(now.getHour < 5 || now.getHour > 20) {
		if(Lampbulb1nexttofire_Brightness.state == 0) {
			logInfo("LoungeRoomMotiontimer", "Motion Detected during night, night light started")
				LampBulb2nexttofire_Color.sendCommand("5,90,5")
				LampBulb2nexttofire_Color.sendCommand("ON")
				Lampbulb1nexttofire_Brightness.sendCommand("5")
				Lampbulb1nexttofire_Color_Temperature.sendCommand("90")
				Lampbulb1nexttofire.sendCommand("ON")
				motionTimer2 = createTimer(now.plusSeconds(30), [ |
					LampBulb2nexttofire_Color.sendCommand("OFF")
					Lampbulb1nexttofire.sendCommand("OFF")
       				])
			} else {
				logInfo("LoungeRoomMotiontimer", "Motion Detected during night, the light was already on")
		} else {
			logInfo("LoungeRoomMotiontimer", "Motion Detected during day, no night light needed")
		}
	}	
end

Awesome, thank you.

Do you think moving the if into a script and calling the script from a rule would make any difference? I mean apart from scene setting if and when I eventually get to that stage.

If you plan to use script files for defining scenes that could be a good idea. But the global Timer variable you have defined wouldn’t be available in a script. You could however extract the

LampBulb2nexttofire_Color.sendCommand("5,90,5")
LampBulb2nexttofire_Color.sendCommand("ON")
Lampbulb1nexttofire_Brightness.sendCommand("5")
Lampbulb1nexttofire_Color_Temperature.sendCommand("90")
Lampbulb1nexttofire.sendCommand("ON")

-part into e.g. night-light.script and replace it in the rule by callScript('night-light'). Then you could call the same script if you want to start the scene from other rules as well.

Scripts are quite limited in many ways, they are completely isolated from the rule that called them, and you cannot pass values to/from them. But for sending a series of predefined commands to items (like a scene) they can be useful, to allow code reuse.

1 Like

No worries. Thanks Anders.