If you are trying to add the command directly to the command string then it gets a bit more complicated since you need to scape everything since there is an outer set of quotes that need escaping. The spaces don’t matter. I don’t have any devices that require dps settings and just added support at the request of others. So I only really tested it as a command line tool and haven’t ever tested against a rule before. The rules are a bit a of a mess but I have was working on getting cloud support and considering just making a proper binding. The previous control script was very unreliable so lots of the crap in the rules was aimed at that, but I should update them with nice clean rules.
I would recommend that you pass the argument to the rule, it helps having to escape everything. So if you pass -set '{"dps":1, "set":true}' to item testTuya it should work fine.
rule "Test dps"
when
Item tesTuya received command
then
var setCommand="node /etc/openhab2/scripts/node_modules/njstuya -ip 10.xx -id xx -key xx " + receivedCommand.toString
var resp = executeCommandLine(setCommand, 5000)
if(db) { logInfo("Tuya", "New broadcast {} resp {}", setCommand, resp) }
end
I would also suggest you pass the item ip, key, id as well or have it as some kind of variable than fixed into separate rules.
But if you want to test it directly or hardcoded then if you escape everything any of the following should work.
As a variable
var setCommand = "'{\"dps\":1,\"set\":true}'"
var resp = executeCommandLine("node /etc/openhab2/scripts/node_modules/njstuya -ip 192.168.xx -id xx -key xx -set " + setCommand, 5000)
Or hardcoded
executeCommandLine("node /etc/openhab2/scripts/node_modules/njstuya -ip 192.168.xx -id xx -key xx -set " + '\'{"dps": 1, "set":true}\'', 5000)
executeCommandLine("node /etc/openhab2/scripts/node_modules/njstuya -ip 192.168.xx -id xx -key xx -set '{\"dps\": 1, \"set\":true}'", 5000)
Edit: I’ve redone the items and rules.
Items
//Tuya items and thermo
// Complete ip/id/key
// Tuya Group Devices
Group gTuyaActions "Tuya Action to run"
Group:Switch gTuyaStates "Tuya devices"
// Tuya devices
Switch LivingRoomHeater "Heater state" (gTuyaStates, gSwitch) [ "Switchable" ]
Switch BedroomHeater "Heater state" (gTuyaStates, gSwitch) [ "Switchable" ]
Number KitchenThermostatCurrentTemp "Kitchen Thermostat Current Temperature" (gKitchenThermostat) //[ "CurrentTemperature" ]
Number KitchenThermostatTargetTemp "Kitchen Thermostat Target Temperature" (gKitchenThermostat) {autoupdate="true"}//[ "TargetTemperature" ]
// Send current time to refresh to be able to query when previous refresh was
String TuyaRefresh "Refresh"
// Tuya Devices with sensistive data edit before sharing.
String LivingRoomHeaterCommand "-ip 10.x.x.x -id xx -key xx" (gTuyaActions)
String BedroomHeaterCommand "-ip 10.x.x.x -id xx -key xx" (gTuyaActions)
Rules
var _DEBUG = false
var db = false
var Timer statusTimer = null
var Timer errorTimer = null
rule "Execute Tuya Action"
when
Member of gTuyaActions received command
then
if(db) logInfo("TUYA", "Group trigger {} command", triggeringItem, receivedCommand)
var setCommand="node /etc/openhab2/scripts/node_modules/njstuya " + triggeringItem.label + " " + receivedCommand.toString
var tuyaDevice = triggeringItem.name.replace('Command','')
// Runs command vis njstuya
var resp = executeCommandLine(setCommand, 5000)
if(resp === null) resp = "Error null"
if(resp.contains("Error") || resp.contains("Warning") || resp.length < 2){
logInfo("Tuya", "Error in response [{}] ", resp)
postUpdate(tuyaDevice, "UNDEF")
// refresh on Error only once after good state.
if (errorTimer === null) {
errorTimer = createTimer(now.plusMillis(1500), [ |
triggeringItem.sendCommand("STATUS")
errorTimer.cancel()
errorTimer = null
])
}
}
else {
if(db) logInfo("Tuya", "Updating state [{}] ", resp)
postUpdate(tuyaDevice, resp)
// Reset errorTimer to null if state is good
if (errorTimer !== null) {
errorTimer.cancel()
errorTimer = null
}
}
if(db) { logInfo("Tuya", "New broadcast {} resp {}", setCommand, resp) }
end
rule "Tuya Refresh"
when
Item TuyaRefresh received command
or
Time cron "13 0/2 * * * ?"
then
gTuyaActions.allMembers.forEach[ device | sendCommand(device, "status")]
end
rule "Update Thermostat Value"
when
Item HueKitchenTemp changed
then
if(db) { logInfo("Thermostat", "update kitchen temp {}", HueKitchenTemp)}
KitchenThermostatCurrentTemp.postUpdate(Float::parseFloat(String::format("%s",HueKitchenTemp.state).replace(' ','')))
end
rule "Control Temp"
when
Item KitchenThermostatCurrentTemp changed
or
Item KitchenThermostatTargetTemp changed
then
logInfo("Thermostat", "Set {} change temperature from {} to {}", LivingRoomHeater ,KitchenThermostatCurrentTemp.state, KitchenThermostatTargetTemp.state)
var isCold = (KitchenThermostatCurrentTemp.state as Number) < (KitchenThermostatTargetTemp.state as Number)
var setCommand = if(isCold) 'ON' else 'OFF'
//When using slider you can get lots of changes, this should prevent lots of commands in a row
if(!LivingRoomHeater.state.toString.contains(setCommand) && statusTimer === null) {
if(db) { logInfo("Thermostat", " logic {} state {} cmd{}", LivingRoomHeater.state.toString.contains(setCommand), LivingRoomHeater.state.toString, setCommand)}
if(db) { logInfo("Thermostat", " is cold {} set command {}", isCold, setCommand)}
LivingRoomHeaterCommand.sendCommand(setCommand)
// Update state
if (statusTimer !== null) {
statusTimer.cancel()
statusTimer = null
}
statusTimer = createTimer(now.plusMillis(1500), [ |
LivingRoomHeaterCommand.sendCommand("STATUS")
statusTimer.cancel()
statusTimer = null
])
} else if (statusTimer !== null) {
statusTimer.cancel()
statusTimer = null
}
end