If ({item}.state <=65)

I have a rule that checks the voltage of my batteries and if it is less then 65% starts the generator. The problem is that the if is always being triggered even when charge is over 65. I think the issue is that the value coming back may be a string.

rule "Battery"
when
Item Battery_Charge changed
then
if (Battery_Charge.state <= 65) {
logInfo("Testing", "Battery_Charged = " + Battery_Charge.state)
        sendCommand(Battery_Low, ON)
        sendMail("8323303810@mms.att.net", "Battery", "Battery SOC at " + Battery_Charge.state + "%" "Load at " +  Inverter_Total_Watts.state + " watts")
        logInfo("Testing", "Generator_State = " + Battery_Charge.state + " Generator_Failed = " + Generator_Failed.state)
        if (Generator_Status.state == OPEN && Generator_Failed.state == OFF) {
                // sendCommand(Generator_Start, ON)
        }
} else if (Battery_Low.state == ON) {
        sendCommand(Battery_Low, OFF)
}
if (Battery_Charge.state >= 90 && Generator_Override == OFF) {
        sendCommand(Generator_Start, OFF)
}
end

What is Battery_Charge’s Item definition?

Number, that is why I thought it would be ok.

Number          Battery_Charge                  "Battery Charge [%d %%]"			<battery>       (Solar)

Yet…

2015-12-08 12:04:05.917 [INFO ] [g.openhab.model.script.Testing] - Generator_State = 99 Generator_Failed = OFF
2015-12-08 12:04:05.976 [INFO ] [runtime.busevents             ] - Generator_Start received command ON

It doesn’t seem consistent how the DSL casts Numbers. Maybe if we force the issue it will get it right:

if((Battery_Charge.state as DecimalType).intValue <= 65)

Similar change needed for the >= 90.

If this doesn’t work, add a logInfo statement printing out Battery_Charge’s state. I suppose it could be a PercentType in which case the value is actually .65 that we want to compare to.

logInfo("Battery", "Battery_Charge state is " + (Battery_Charge.state as DecimalType).doubleValue)

Per the code, Number items’ states can only be DecimalType or UnDefType.

What is the output of your line

logInfo("Testing", "Battery_Charged = " + Battery_Charge.state)

UPDATE: Also, since your item Battery_Charge is not bound to a binding, where is it getting its state value from?

Also (unrelated), your line

if (Battery_Charge.state >= 90 && Generator_Override == OFF) {

should probably be

if (Battery_Charge.state >= 90 && Generator_Override.state == OFF) {

if Generator_Override is an item.

rule "Battery"
when
Item Battery_Charge changed
then
logInfo("`Testing", "Battery_Charged = " + Battery_Charge.state)
if ((Battery_Charge.state as DecimalType).intValue <= 65) {
logInfo("`Testing", "Battery_Charged = " + Battery_Charge.state)
        sendCommand(Battery_Low, ON)
        sendMail("8323303810@mms.att.net", "Battery", "Battery SOC at " + Battery_Charge.state + "%" "Load at " +  Inverter_Total_Watts.state + " watts")
        logInfo("Testing", "Generator_State = " + Battery_Charge.state + " Generator_Failed = " + Generator_Failed.state)
        if (Generator_Status.state == OPEN && Generator_Failed.state == OFF) {
                // sendCommand(Generator_Start, ON)
        }
} else if (Battery_Low.state == ON) {
        sendCommand(Battery_Low, OFF)
}
if ((Battery_Charge.state as DecimalType).intValue >= 90 && Generator_Override == OFF) {
        sendCommand(Generator_Start, OFF)
}
end

And logs.

2015-12-08 14:10:54.480 [INFO ] [.openhab.model.script.`Testing] - Battery_Charged = 100
2015-12-08 14:10:54.494 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Battery': Cannot cast org.openhab.core.library.types.DecimalType to void

Thanks for the .state feedback, you were right.

As far as the value, its getting it from JSONPATH from this rule:

 import java.lang.*
import org.openhab.core.library.types.*

rule "Outback JSON parsing"
when
Item Outback_Dev_status changed
then
var String json = Outback_Dev_status.state.toString
var Number battery_soc = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].SOC", json))
var Number battery_voltage = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Batt_V", json))
var String battery_temp_string = new String(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Batt_temp", json))
	var Number battery_temp = new Integer(battery_temp_string.split(" ").get(0))
	var Number shunt_a_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Shunt_A_I", json))
var Number shunt_b_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Shunt_B_I", json))
	var Number shunt_total_amps = shunt_a_amps + shunt_b_amps
var Number today_out_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Out_kWh_today", json))
var Number charge_a_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==5)][0].Out_I", json))
var Number charge_b_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==6)][0].Out_I", json))
var Number charge_c_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==7)][0].Out_I", json))
var Number charge_d_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==8)][0].Out_I", json))
var Number charge_a_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==5)][0].Out_kWh", json))
var Number charge_b_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==6)][0].Out_kWh", json))
var Number charge_c_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==7)][0].Out_kWh", json))
var Number charge_d_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==8)][0].Out_kWh", json))
var Number charge_a_watts = charge_a_amps * battery_voltage
var Number charge_b_watts = charge_b_amps * battery_voltage
var Number charge_c_watts = charge_c_amps * battery_voltage
var Number charge_d_watts = charge_d_amps * battery_voltage
var Number total_watts = charge_a_watts + charge_b_watts + charge_c_watts + charge_d_watts
	var Number today_solar_kwh = charge_a_kwh + charge_b_kwh + charge_c_kwh + charge_d_kwh
	
postUpdate(Battery_Charge, battery_soc)
postUpdate(Battery_Voltage, battery_voltage)
	postUpdate(Battery_Temp, battery_temp * 1.8 + 32)
postUpdate(Solar_Charge_A_Watts, charge_a_watts)
postUpdate(Solar_Charge_B_Watts, charge_b_watts)
postUpdate(Solar_Charge_C_Watts, charge_c_watts)
postUpdate(Solar_Charge_D_Watts, charge_d_watts)
postUpdate(Solar_Total_Watts, total_watts)
	postUpdate(Shunt_A_Amps, shunt_a_amps)
	postUpdate(Shunt_B_Amps, shunt_b_amps)
	postUpdate(Shunt_Total_Amps, shunt_total_amps)
	postUpdate(Today_Out_kWh, today_out_kwh)
	postUpdate(Today_Solar_kWh, today_solar_kwh)

var Number a_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].VAC_out_L1", json))
var Number a_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Buy_I_L1", json))
var Number a_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Inv_I_L1", json))
var Number a_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].VAC_out_L2", json))
var Number a_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Buy_I_L2", json))
var Number a_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Inv_I_L2", json))
	var Number a_l1_buy_watts = a_l1_voltage * a_l1_buy_amps
	var Number a_l2_buy_watts = a_l1_voltage * a_l2_buy_amps
	var Number buy_a_watts = a_l1_buy_watts + a_l2_buy_watts
	var Number a_l1_watts = a_l1_voltage * a_l1_inv_amps
	var Number a_l2_watts = a_l2_voltage * a_l2_inv_amps
	var Number inverter_a_watts = a_l1_watts + a_l2_watts

	postUpdate(Buy_A_Watts, buy_a_watts)
	postUpdate(Inverter_A_Watts, inverter_a_watts)

var Number b_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].VAC_out_L1", json))
var Number b_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Buy_I_L1", json))
var Number b_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Inv_I_L1", json))
var Number b_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].VAC_out_L2", json))
var Number b_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Buy_I_L2", json))
var Number b_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Inv_I_L2", json))
	var Number b_l1_buy_watts = b_l1_voltage * b_l1_buy_amps
	var Number b_l2_buy_watts = b_l1_voltage * b_l2_buy_amps
	var Number buy_b_watts = b_l1_buy_watts + b_l2_buy_watts
	var Number b_l1_watts = b_l1_voltage * b_l1_inv_amps
	var Number b_l2_watts = b_l2_voltage * b_l2_inv_amps
	var Number inverter_b_watts = b_l1_watts + b_l2_watts

	postUpdate(Buy_B_Watts, buy_b_watts)
	postUpdate(Inverter_B_Watts, inverter_b_watts)

var Number c_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].VAC_out_L1", json))
var Number c_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Buy_I_L1", json))
var Number c_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Inv_I_L1", json))
var Number c_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].VAC_out_L2", json))
var Number c_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Buy_I_L2", json))
var Number c_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Inv_I_L2", json))
	var Number c_l1_buy_watts = c_l1_voltage * c_l1_buy_amps
	var Number c_l2_buy_watts = c_l1_voltage * c_l2_buy_amps
	var Number buy_c_watts = c_l1_buy_watts + c_l2_buy_watts
	var Number c_l1_watts = c_l1_voltage * c_l1_inv_amps
	var Number c_l2_watts = c_l2_voltage * c_l2_inv_amps
	var Number inverter_c_watts = c_l1_watts + c_l2_watts

	postUpdate(Buy_C_Watts, buy_c_watts)
	postUpdate(Inverter_C_Watts, inverter_c_watts)

	postUpdate(Inverter_Total_Watts, inverter_a_watts + inverter_b_watts + inverter_c_watts)
	postUpdate(Buy_Total_Watts, buy_a_watts + buy_b_watts + buy_c_watts)
end

Woa, this doesn’t make sense.

The Item is defined as a Number. @watou confirmed from the code itself that it can only hold a DecimalType (or UnDefType). We know it isn’t UnDefType because we get the state printed in the logs. But it says that the State isn’t a DecimalType and that the state is void.

I don’t see how any of this is possible. Clearly I’m missing something.

Ya, its odd.

2015-12-08 14:25:42.050 [INFO ] [.openhab.model.script.`Testing] - Battery_Charged = 99
2015-12-08 14:25:42.050 [INFO ] [runtime.busevents             ] - Battery_Charge state updated to 99
2015-12-08 14:25:42.050 [INFO ] [g.openhab.model.script.Testing] - Generator_State = 99 Generator_Failed = OFF

So looking at the rule below and the output. The state changes, my log shows 99 as a value (checked its not .99). I then see the log in inside my if that I don’t expect to see because its not <= 65.

rule "Battery"
when
Item Battery_Charge changed
then
logInfo("`Testing", "Battery_Charged = " + Battery_Charge.state)
if (Battery_Charge.state < 65) {
logInfo("`Testing", "Battery_Charged = " + Battery_Charge.state)
        sendCommand(Battery_Low, ON)
        sendMail("8323303810@mms.att.net", "Battery", "Battery SOC at " + Battery_Charge.state + "%" "Load at " +  Inverter_Total_Watts.state + " watts")
        logInfo("Testing", "Generator_State = " + Battery_Charge.state + " Generator_Failed = " + Generator_Failed.state)
        if (Generator_Status.state == OPEN && Generator_Failed.state == OFF) {
                // sendCommand(Generator_Start, ON)
        }
} else if (Battery_Low.state == ON) {
        sendCommand(Battery_Low, OFF)
}
if (Battery_Charge.state  >= 90 && Generator_Override.state == OFF) {
        sendCommand(Generator_Start, OFF)
}
end

Very indirect suggestion, but in your JSON parsing code if you moved

postUpdate(Battery_Charge, battery_soc)

to the bottom of it all, the other items you reference would (probably) have their values set by the time the changed rule runs, whereas you are now posting it first, meaning the rule might be running before the other items have gotten their values. I would consider the timing of these two potentially overlapping rules.

…adding, using locks to disallow two threads from running the rules concurrently might be a good idea.

I don’t understand why the worked, but it did! Any pointers on locks? Or is it a better idea to just combine the rules?

It worked* because some of your referenced items had not yet gotten their states. Very soon after posting an update to your Battery_Charge item in the big rule [1], that Item Battery_Charge changed rule [2] ran, but before the [1] had finished posting states to the other items you reference in [2]. I think it’s better to have a rule for each logical unit, much like how you’ve divided them now.

(*well, I’m guessing that’s why it worked.)

Locking example fragment:

import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
// ...
var Lock lock = new ReentrantLock()

rule rule1
when something
then
  lock.lock()
  // do something atomically so another locked rule won't
  // run until I'm done
  lock.unlock()
end

rule rule2
when something_else
then
  lock.lock()
  // do something atomically so another locked rule won't
  // run until I'm done
  lock.unlock()
end

Tried the lock thing and it’s not fixing the problem.

2015-12-09 10:19:49.345 [INFO ] [runtime.busevents             ] - Battery_Charge state updated to 68
2015-12-09 10:19:49.348 [INFO ] [runtime.busevents             ] - Buy_Total_Watts state updated to 0
2015-12-09 10:19:49.371 [INFO ] [.openhab.model.script.`Testing] - Battery_Charged = 68
2015-12-09 10:19:49.431 [INFO ] [runtime.busevents             ] - Generator_Start received command ON
2015-12-09 10:19:51.868 [INFO ] [runtime.busevents             ] - Generator_Start state updated to ON

The rule started my generator but it was NOT less then or equal to 65.

import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock

var Lock lock = new ReentrantLock()

rule "Battery State Events"
when
Item Battery_Charge changed
then
lock.lock()
logInfo("`Testing", "Battery_Charged = " + Battery_Charge.state)
if (Battery_Charge.state <= 65) {
logInfo("`Testing", "(Inside if)Battery_Charged = " + Battery_Charge.state)
sendCommand(Battery_Low, ON)
sendMail("8323303810@mms.att.net", "Battery", "Battery SOC at " + Battery_Charge.state + "%" "Load at " +  Inverter_Total_Watts.state + " watts")
if (Generator_Status.state == OPEN && Generator_Failed.state == OFF) {
sendCommand(Generator_Start, ON)
}
} else if (Battery_Low.state == ON) {
logInfo("`Testing", "(Inside else if)Battery_Charged = " + Battery_Charge.state)

sendCommand(Battery_Low, OFF)
}
if (Battery_Charge.state  >= 90 && Generator_Override.state == OFF) {
sendCommand(Generator_Start, OFF)
}
lock.unlock()
end

It looks like based on the logs that “if (Battery_Charge.state <= 65)” is not triggering because I never saw the “logInfo(”`Testing", “(Inside if)Battery_Charged = " + Battery_Charge.state)” log line. But what I don’t understand is why the “if (Generator_Status.state == OPEN && Generator_Failed.state == OFF)” triggered when it is inside the “if (Battery_Charge.state <= 65)” that did not.

import java.lang.*
import org.openhab.core.library.types.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock

var Lock lock = new ReentrantLock()

rule "Outback JSON parsing"
when
Item Outback_Dev_status changed
then	
	lock.lock()
var String json = Outback_Dev_status.state.toString
var Number battery_soc = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].SOC", json))
var Number battery_voltage = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Batt_V", json))
var String battery_temp_string = new String(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Batt_temp", json))
	var Number battery_temp = new Integer(battery_temp_string.split(" ").get(0))
	var Number shunt_a_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Shunt_A_I", json))
var Number shunt_b_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Shunt_B_I", json))
	var Number shunt_total_amps = shunt_a_amps + shunt_b_amps
var Number today_out_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Out_kWh_today", json))
var Number charge_a_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==5)][0].Out_I", json))
var Number charge_b_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==6)][0].Out_I", json))
var Number charge_c_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==7)][0].Out_I", json))
var Number charge_d_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==8)][0].Out_I", json))
var Number charge_a_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==5)][0].Out_kWh", json))
var Number charge_b_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==6)][0].Out_kWh", json))
var Number charge_c_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==7)][0].Out_kWh", json))
var Number charge_d_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==8)][0].Out_kWh", json))
var Number charge_a_watts = charge_a_amps * battery_voltage
var Number charge_b_watts = charge_b_amps * battery_voltage
var Number charge_c_watts = charge_c_amps * battery_voltage
var Number charge_d_watts = charge_d_amps * battery_voltage
var Number total_watts = charge_a_watts + charge_b_watts + charge_c_watts + charge_d_watts
	var Number today_solar_kwh = charge_a_kwh + charge_b_kwh + charge_c_kwh + charge_d_kwh
	
postUpdate(Battery_Charge, battery_soc)
postUpdate(Battery_Voltage, battery_voltage)
	postUpdate(Battery_Temp, battery_temp * 1.8 + 32)
postUpdate(Solar_Charge_A_Watts, charge_a_watts)
postUpdate(Solar_Charge_B_Watts, charge_b_watts)
postUpdate(Solar_Charge_C_Watts, charge_c_watts)
postUpdate(Solar_Charge_D_Watts, charge_d_watts)
postUpdate(Solar_Total_Watts, total_watts)
	postUpdate(Shunt_A_Amps, shunt_a_amps)
	postUpdate(Shunt_B_Amps, shunt_b_amps)
	postUpdate(Shunt_Total_Amps, shunt_total_amps)
	postUpdate(Today_Out_kWh, today_out_kwh)
	postUpdate(Today_Solar_kWh, today_solar_kwh)

var Number a_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].VAC_out_L1", json))
var Number a_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Buy_I_L1", json))
var Number a_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Inv_I_L1", json))
var Number a_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].VAC_out_L2", json))
var Number a_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Buy_I_L2", json))
var Number a_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Inv_I_L2", json))
	var Number a_l1_buy_watts = a_l1_voltage * a_l1_buy_amps
	var Number a_l2_buy_watts = a_l1_voltage * a_l2_buy_amps
	var Number buy_a_watts = a_l1_buy_watts + a_l2_buy_watts
	var Number a_l1_watts = a_l1_voltage * a_l1_inv_amps
	var Number a_l2_watts = a_l2_voltage * a_l2_inv_amps
	var Number inverter_a_watts = a_l1_watts + a_l2_watts

	postUpdate(Buy_A_Watts, buy_a_watts)
	postUpdate(Inverter_A_Watts, inverter_a_watts)

var Number b_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].VAC_out_L1", json))
var Number b_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Buy_I_L1", json))
var Number b_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Inv_I_L1", json))
var Number b_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].VAC_out_L2", json))
var Number b_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Buy_I_L2", json))
var Number b_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Inv_I_L2", json))
	var Number b_l1_buy_watts = b_l1_voltage * b_l1_buy_amps
	var Number b_l2_buy_watts = b_l1_voltage * b_l2_buy_amps
	var Number buy_b_watts = b_l1_buy_watts + b_l2_buy_watts
	var Number b_l1_watts = b_l1_voltage * b_l1_inv_amps
	var Number b_l2_watts = b_l2_voltage * b_l2_inv_amps
	var Number inverter_b_watts = b_l1_watts + b_l2_watts

	postUpdate(Buy_B_Watts, buy_b_watts)
	postUpdate(Inverter_B_Watts, inverter_b_watts)

var Number c_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].VAC_out_L1", json))
var Number c_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Buy_I_L1", json))
var Number c_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Inv_I_L1", json))
var Number c_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].VAC_out_L2", json))
var Number c_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Buy_I_L2", json))
var Number c_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Inv_I_L2", json))
	var Number c_l1_buy_watts = c_l1_voltage * c_l1_buy_amps
	var Number c_l2_buy_watts = c_l1_voltage * c_l2_buy_amps
	var Number buy_c_watts = c_l1_buy_watts + c_l2_buy_watts
	var Number c_l1_watts = c_l1_voltage * c_l1_inv_amps
	var Number c_l2_watts = c_l2_voltage * c_l2_inv_amps
	var Number inverter_c_watts = c_l1_watts + c_l2_watts

	postUpdate(Buy_C_Watts, buy_c_watts)
	postUpdate(Inverter_C_Watts, inverter_c_watts)

	postUpdate(Inverter_Total_Watts, inverter_a_watts + inverter_b_watts + inverter_c_watts)
	postUpdate(Buy_Total_Watts, buy_a_watts + buy_b_watts + buy_c_watts)
	lock.unlock()
end

Do your two rules live in the same .rules file? That have to be sharing that lock variable which means that have to be in the same file.

1 Like

Ahh… no they do not.

Having issues with the Battery State Events rule unlocking.

2015-12-15 14:49:11.672 [INFO ] [g.openhab.model.script.Testing] - JSON - Locking
2015-12-15 14:49:11.678 [INFO ] [g.openhab.model.script.Testing] - JSON - Unlocked
2015-12-15 14:49:11.686 [INFO ] [g.openhab.model.script.Testing] - Battery - Locking
2015-12-15 14:49:11.716 [INFO ] [g.openhab.model.script.Testing] - Battery_Charge = 89
2015-12-15 14:49:11.736 [INFO ] [g.openhab.model.script.Testing] - Generator_Auto = OFF
2015-12-15 14:49:32.364 [INFO ] [g.openhab.model.script.Testing] - JSON - Locking
2015-12-15 14:49:53.476 [INFO ] [g.openhab.model.script.Testing] - JSON - Locking

The JSON part locks and unlocks, but the Battery section just Locked and I never see the log line saying it was unlocked.

Full rules file:

import java.lang.*
import org.openhab.core.library.types.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock

var Lock lock = new ReentrantLock()

rule "Outback JSON parsing"
when
Item Outback_Dev_status changed
then	
	logInfo("Testing", "JSON - Locking")
	lock.lock()
	var String json = Outback_Dev_status.state.toString
var Number battery_soc = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].SOC", json))
var Number battery_voltage = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Batt_V", json))
var String battery_temp_string = new String(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Batt_temp", json))
	var Number battery_temp = new Integer(battery_temp_string.split(" ").get(0))
	var Number shunt_a_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Shunt_A_I", json))
var Number shunt_b_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Shunt_B_I", json))
	var Number shunt_total_amps = shunt_a_amps + shunt_b_amps
var Number today_out_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==10)][0].Out_kWh_today", json))
var Number charge_a_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==5)][0].Out_I", json))
var Number charge_b_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==6)][0].Out_I", json))
var Number charge_c_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==7)][0].Out_I", json))
var Number charge_d_amps = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==8)][0].Out_I", json))
var Number charge_a_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==5)][0].Out_kWh", json))
var Number charge_b_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==6)][0].Out_kWh", json))
var Number charge_c_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==7)][0].Out_kWh", json))
var Number charge_d_kwh = new Double(transform("JSONPATH", "$.devstatus.ports[?(@.Port==8)][0].Out_kWh", json))
var Number charge_a_watts = charge_a_amps * battery_voltage
var Number charge_b_watts = charge_b_amps * battery_voltage
var Number charge_c_watts = charge_c_amps * battery_voltage
var Number charge_d_watts = charge_d_amps * battery_voltage
var Number total_watts = charge_a_watts + charge_b_watts + charge_c_watts + charge_d_watts
	var Number today_solar_kwh = charge_a_kwh + charge_b_kwh + charge_c_kwh + charge_d_kwh
	
postUpdate(Battery_Charge, battery_soc)
postUpdate(Battery_Voltage, battery_voltage)
	postUpdate(Battery_Temp, battery_temp * 1.8 + 32)
postUpdate(Solar_Charge_A_Watts, charge_a_watts)
postUpdate(Solar_Charge_B_Watts, charge_b_watts)
postUpdate(Solar_Charge_C_Watts, charge_c_watts)
postUpdate(Solar_Charge_D_Watts, charge_d_watts)
postUpdate(Solar_Total_Watts, total_watts)
	postUpdate(Shunt_A_Amps, shunt_a_amps)
	postUpdate(Shunt_B_Amps, shunt_b_amps)
	postUpdate(Shunt_Total_Amps, shunt_total_amps)
	postUpdate(Today_Out_kWh, today_out_kwh)
	postUpdate(Today_Solar_kWh, today_solar_kwh)

var Number a_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].VAC_out_L1", json))
var Number a_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Buy_I_L1", json))
var Number a_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Inv_I_L1", json))
var Number a_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].VAC_out_L2", json))
var Number a_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Buy_I_L2", json))
var Number a_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==1)][0].Inv_I_L2", json))
	var Number a_l1_buy_watts = a_l1_voltage * a_l1_buy_amps
	var Number a_l2_buy_watts = a_l1_voltage * a_l2_buy_amps
	var Number buy_a_watts = a_l1_buy_watts + a_l2_buy_watts
	var Number a_l1_watts = a_l1_voltage * a_l1_inv_amps
	var Number a_l2_watts = a_l2_voltage * a_l2_inv_amps
	var Number inverter_a_watts = a_l1_watts + a_l2_watts

	postUpdate(Buy_A_Watts, buy_a_watts)
	postUpdate(Inverter_A_Watts, inverter_a_watts)

var Number b_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].VAC_out_L1", json))
var Number b_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Buy_I_L1", json))
var Number b_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Inv_I_L1", json))
var Number b_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].VAC_out_L2", json))
var Number b_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Buy_I_L2", json))
var Number b_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==2)][0].Inv_I_L2", json))
	var Number b_l1_buy_watts = b_l1_voltage * b_l1_buy_amps
	var Number b_l2_buy_watts = b_l1_voltage * b_l2_buy_amps
	var Number buy_b_watts = b_l1_buy_watts + b_l2_buy_watts
	var Number b_l1_watts = b_l1_voltage * b_l1_inv_amps
	var Number b_l2_watts = b_l2_voltage * b_l2_inv_amps
	var Number inverter_b_watts = b_l1_watts + b_l2_watts

	postUpdate(Buy_B_Watts, buy_b_watts)
	postUpdate(Inverter_B_Watts, inverter_b_watts)

var Number c_l1_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].VAC_out_L1", json))
var Number c_l1_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Buy_I_L1", json))
var Number c_l1_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Inv_I_L1", json))
var Number c_l2_voltage = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].VAC_out_L2", json))
var Number c_l2_buy_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Buy_I_L2", json))
var Number c_l2_inv_amps = new Integer(transform("JSONPATH", "$.devstatus.ports[?(@.Port==3)][0].Inv_I_L2", json))
	var Number c_l1_buy_watts = c_l1_voltage * c_l1_buy_amps
	var Number c_l2_buy_watts = c_l1_voltage * c_l2_buy_amps
	var Number buy_c_watts = c_l1_buy_watts + c_l2_buy_watts
	var Number c_l1_watts = c_l1_voltage * c_l1_inv_amps
	var Number c_l2_watts = c_l2_voltage * c_l2_inv_amps
	var Number inverter_c_watts = c_l1_watts + c_l2_watts

	postUpdate(Buy_C_Watts, buy_c_watts)
	postUpdate(Inverter_C_Watts, inverter_c_watts)

	postUpdate(Inverter_Total_Watts, inverter_a_watts + inverter_b_watts + inverter_c_watts)
	postUpdate(Buy_Total_Watts, buy_a_watts + buy_b_watts + buy_c_watts)
	lock.unlock()
	logInfo("Testing", "JSON - Unlocked")
end

rule "Battery State Events"
when
Item Battery_Charge changed
then	
	logInfo("Testing", "Battery - Locking")
	lock.lock()
	logInfo("Testing", "Battery_Charge = " + Battery_Charge.state)
	logInfo("Testing", "Generator_Auto = " + Generator_Auto.state)
	if (Battery_Charged.state >= 90 && Generator_Auto.state == ON) {
		sendCommand(Battery_Low, OFF)
		sendCommand(Generator_Auto, OFF)
	}
	
	if (Battery_Charged.state <= 60) {
		sendCommand(Battery_Low, ON)
		if (Generator_Status.state == OPEN && Generator_Auto.state == OFF && Generator_Failed.state == OFF) {
			sendMail("8323303810@mms.att.net", "Battery", "Battery SOC at " + Battery_Charged.state + "%" "Load at " +  Inverter_Total_Watts.state + " watts")
				sendCommand(Generator_Auto, ON)
		}
	}
	lock.unlock()
	logInfo("Testing", "Battery - Unlocked")
end

There doesn’t appear to be any reason why the end of that rule is not executing as far as I can tell. One thing I do whenever I use locks is wrap the transaction into a try/catch/finally clause and put the unlock into the finally. Theoretically the finally clause will always get called no matter what happens. In practice though I’ve found that certain types of errors will cause the rule to completely bail without executing the finally. But it couldn’t hurt.

It would look like this:

lock.lock()
try {
    // do your stuff here
}
catch(Throwable t) {
    logError("Name", "Error occurred during rule...")
}
finally {
     lock.unlock()
}
1 Like