Openhab running on RPi3 with AEON Z-Wave Stick gen5
Z-Wave Fibaro Dimmers connected to ceiliing lights
Fibaro multi sensor (motion, light, temperature)
The dimmers work accordingly (e.g. dimming to various % and ON/OFF), however I have tried to implement an automatic light dimming system and the behaviour of the lights/dimmers is not as intended. The main problems:
The lights are set to increase/decrease in steps of 3%: this does not always happen; at times the lights clearly increase/decrease by large steps (e.g from 10% to 50%)
The “automatic light dimming” should start when: the LUX in the room is a certain value, a virtual switch is ON (standard_ALD) and some WiFi presence
However, the lights keep on dimming automatically even when the virtual switch is changed to OFF.
Rule:
/* Automatic Light Dimming */
var Number Dimmer_1_Value = 0
var Number Dimmer_2_Value = 0
var Number Dimmer_3_Value = 0
var Number Dimmer_4_Value = 0
rule "Dimming Up: Entrance"
when
Item ZwaveEye1Lux changed
then
if (((ZwaveEye1Lux.state as DecimalType) <= ( LuxSetpoint.state as DecimalType - 30)) && (Standard_ALD.state == ON) && (Presence_Mobile_Mike.state == ON || Presence_Iris_Saxion.state == ON || Presence_Pepijn_Saxion.state == ON || Presence_Diamant_Saxion.state == ON || Presence_Euan_Saxion.state == ON ))
{
Dimmer_1_Value = Dimmer_1.state as PercentType
Dimmer_1_Value = Dimmer_1_Value + 3
Dimmer_2_Value = Dimmer_2.state as PercentType
Dimmer_2_Value = Dimmer_2_Value + 3
Thread::sleep(5000)
sendCommand(Dimmer_1,Dimmer_1_Value)
sendCommand(Dimmer_2, Dimmer_2_Value)
}
end
rule "Dimming Down: Entrance"
when
Item ZwaveEye1Lux changed
then
if (((ZwaveEye1Lux.state as DecimalType) >= ( LuxSetpoint.state as DecimalType + 30)) && (Standard_ALD.state == ON) && (Presence_Mobile_Mike.state == ON || Presence_Iris_Saxion.state == ON || Presence_Pepijn_Saxion.state == ON || Presence_Diamant_Saxion.state == ON || Presence_Euan_Saxion.state == ON ))
{
Dimmer_1_Value = Dimmer_1.state as PercentType
Dimmer_1_Value = Dimmer_1_Value - 3
Dimmer_2_Value = Dimmer_2.state as PercentType
Dimmer_2_Value = Dimmer_2_Value - 3
Thread::sleep(5000)
sendCommand(Dimmer_1,Dimmer_1_Value)
sendCommand(Dimmer_2, Dimmer_2_Value)
}
end
I would logInfo() so that you can see when each rule has been triggered.
Might as well use those to log the values of the compared lux Items too.
Bear in mind there is no lock on your rules - if lux changes again while a rule is waiting in a sleep, another copy of the rule is fired up and actioned. You may have a whole bunch running in parallel.
Thanks alot for the help! funnily enough I was just reading your thread regarding locks on the back of @rossko57 advice! I will try your suggested code on monday and provide feedback in case anyone else is interested.
You check if the lock is locked, but never actually lock it yourself
You try to unlock in both the catch clause and the finally clause
You are catching Throwable
To solve the second point, remove entranceLock.unlock from the catch. The finally clause will always run, even after a catch block. The catch of Throwable becomes useless as there’s nothing to do. It’s bad practice to catch Throwable anyway, because that includes things like OutOfMemoryError which you are not handling and therefore should be propagated up the call stack rather than being masked.
To solve the first point, you have a few choices, depending on your intention. If you want to always run the rule body, and if necessary wait for the lock to be released by whoever currently has it, then do something like this:
Is indeed a mistake. I remember writing the lock but must have weed it out when I copied and pasted. One of the problems of wiring coffee on a phone.
Based on experience, at least from 1.8 I’ve seen inconsistent behavior with finally NOT being executed when an exception actually occurs. This may be fixed now but I got in the habit of unlocking in both because of things experience. That is how finally is supposed to work but that isn’t how it worked in the Rules DSL at some point. I spent about a man week figuring this out the hard way.
Indeed in normal Java One shouldn’t catch Error, but I do this so that I will at least get a chance to see what rule caused the Error. Otherwise there is nothing in the log to let you correlate the Error with the rule. This is all theoretical of course as I’ve never seen an Error in OH. I will agree that if a Error is caught it should be rethrown. However that again brings 2 to the for as, at in my experience, the finally will not execute as it should.
Rule (identical to your example tutorial apart from && replacing “and” in the else if statement):
rule "System started"
when
System started
then
Present.sendCommand(OFF) // assume no one is home on startup
end
rule "gPresent updated, at least one sensor changed state"
when
Item gPresent received update
then
// someone came home
if(gPresent.state == ON && Present.state != ON) {
Present_Timer.postUpdate(OFF) // cancel the timer if necessary
Present.sendCommand(ON)
}
// no one is home
else if(gPresent.state == OFF && Present.state != OFF){
Present_Timer.sendCommand(ON) // start the timer
}
end
rule "Present_Timer expired"
when
Item Present_Timer received command OFF
then
Present.sendCommand(OFF)
end
My understanding is that the switch “Present” should be ON if anyone of the WiFi connections in the group (gPresent) are connected right? At the moment, there are two main issues;
The switch “Present” is only ON when all the WiFi connections in the gPresent group are connected, thus it is acting as an AND switch rather than an OR switch
The switch “Present” does not switch OFF when all WiFi connections are off, in fact it only switches OFF on restart (as per the rule)
However, while checking the log (events.log) the group gPresent receives the ON/OFF commands correctly (e.g. `gPresent changed from ON to OFF through Presence_Mobile_Mike``) and the Timer is also sent the ON command correctly, but it does not change the state of the switch after the 1 minute.
Any ideas?
Update: Infact according to the log it appears that the the item “Present_Timer” receives the ON command multiple times once all WiFi connections are off:
2017-06-28 12:31:12.427 [ItemCommandEvent ] - Item 'Present_Timer' received command ON
2017-06-28 12:31:16.409 [ItemStateChangedEvent ] - Presence_Mobile_Mike changed from ON to OFF
2017-06-28 12:31:16.423 [ItemStateChangedEvent ] - network_device_192_168_2_163_online changed from ON to OFF
2017-06-28 12:31:16.429 [ItemStateChangedEvent ] - network_device_192_168_2_163_time changed from 304.38349599999997963095665909349918365478515625 to -1
2017-06-28 12:31:16.437 [ItemCommandEvent ] - Item 'Present_Timer' received command ON
2017-06-28 12:32:06.401 [ItemStateChangedEvent ] - network_device_192_168_2_164_time changed from 1.0822860000000000813002998256706632673740386962890625 to 0.4622370000000000089812601800076663494110107421875
2017-06-28 12:32:12.430 [ItemCommandEvent ] - Item 'Present_Timer' received command ON
2017-06-28 12:32:12.442 [ItemCommandEvent ] - Item 'Present_Timer' received command ON
However the timer never receives the OFF command and thus Presence does not switch OFF either. I am thinking the error is related to the expire binding at this point? Is there anything that has to be configured for this binding?
First thing I would do (not being an authority of any sort) is to analyze the setup. Z-wave networks can sometimes create a lot of delay in terms of actual response (depending on the routing nodes).
Second thing I would think about is as @rlkoshak and @rossko57 stated, triggered rule execution.
Third thing I am thinking about is that the way you are trying to achieve a constant lighting setup. The way you have written the rule will for sure expose your measured light level values to a lot of unsatisfying values! The control method is purely wrong (at least in my opinion). If it works for you, then keep it as it is, if not, find a control method that can fulfill the need, like PID control!
Thanks for the feedback. In regards to the control system; indeed I agree it is rather rudimentary (simple negative feedback loop) - however implementing a control system such as PID would involve finding the transfer function and then tuning the various parameters with unit step response etc. which to be done efficiently requires software (such as 20sim) and/or matlab and at the moment I simply do not have the time for it - furthermore, how would the PID actions be implemented in OpenHAB rules? is there an in built function in the rules or something similar? If you have a link to some good content regarding PID and OpenHab I would be very interested in reading further upon it. Cheers!
A few months ago I pull requested a PID controller binding. Take a look here.
I have tested it with constant lighting, ambient temperature control, and other relatively fast processes (loop time less than 200ms) - for my setups it worked like a charm!.
I am glad I find someone to be interested in PID control, I can provide the jar when requested (momentarily I am trying to keep the tests of the binding applied to my existing running projects, that is why I am not publicly promoting this).
I was wondering if you have any ideas why the following code is not working as intended. From what I can tell the, entranceLock never unclocks ; what happens is that the dimmers increase once, then nothing happens anymore.
import java.util.concurrent.locks.ReentrantLock
var java.util.concurrent.locks.ReentrantLock entranceLock = new java.util.concurrent.locks.ReentrantLock()
var Number Dimmer_1_Value = 0
var Number Dimmer_2_Value = 0
var Number Dimmer_3_Value = 0
var Number Dimmer_4_Value = 0
rule "Dimming UP: Entrance"
when
Item ZwaveEye1Lux changed
then
if(!entranceLock.isLocked) {
entranceLock.lock()
try {
if(ZwaveEye1Lux.state as DecimalType <= LuxSetpoint.state as DecimalType &&
Standard_ALD.state == ON &&
Present.state == ON){
Dimmer_1_Value = Dimmer_1.state as PercentType
Dimmer_1_Value = Dimmer_1_Value + 3
Dimmer_2_Value = Dimmer_2.state as PercentType
Dimmer_2_Value = Dimmer_2_Value + 3
Thread::sleep(1000)
sendCommand(Dimmer_1,Dimmer_1_Value)
sendCommand(Dimmer_2, Dimmer_2_Value)
}
}
catch(Throwable t) { entranceLock.unlock() }
finally { entranceLock.unlock() }
}
end
What is in your logs? Add some logInfos to trace progress and expected values. Errors in try blocks don’t always seem to end up at the catch or finally blocks in rules.
Absolutely add some logging to the main try, the catch, and the finally. In the catch, log out t.toString so we can see what is being thrown.
Try loading it in Eclispe Smarthome Designer to see if there is some syntax problem that is not apparent.
Finally, this isn’t the cause of an error, but when you import java.util.concurrent.locks.ReentrantLock, you only need to refer to it as ReentrantLock in your code. That is the main purpose of imports.
Hello, I will add the logs as soon as I can. Yes I tried various options to make the code work including the import declaration you mention (I saw it in some example code), I did think it didn’t make sense but I still tried it! Anyway, regarding this line of code:
if(ZwaveEye1Lux.state as DecimalType <= LuxSetpoint.state as DecimalType &&
Standard_ALD.state == ON &&
Present.state == ON){
Dimmer_1_Value = Dimmer_1.state as PercentType
Dimmer_1_Value = Dimmer_1_Value + 3
Dimmer_2_Value = Dimmer_2.state as PercentType
Dimmer_2_Value = Dimmer_2_Value + 3
Thread::sleep(1000)
sendCommand(Dimmer_1,Dimmer_1_Value)
sendCommand(Dimmer_2, Dimmer_2_Value)
}
}
If the virtual switch (Standard_ALD ) is switched OFF while the rule is running, then technically the rule should not execute the next time the if statement is cheked, as the dimmers keep on receiving commands even if the switch is turned OFF. The rule initially responds to the switch, as the dimmers only start receiving commands once the switch is turned ON. Any ideas? I wouldn’t think this should happen regardless of the lock/unlock issue?
Like has been suggested, you need to add log statements all over the place in this rule to see exactly where it is getting to, the states of your Items, at each part of the rule.
Dealing with concurrency is really hard and doing it blind is all but impossible.
Fair enough, it makes sense! I will post an update once I can. I just thought a switch being OFF (thus the IF condition not being met) would cause the rule to stop running! Anyway thanks for the support everyone, this community is really great!