This tutorial enables you to control a device with an IR remote using a single item and Google Assistant. I’m using it to with a Rowenta pedestal fan, but it can be broadly applied to any IR-controlled device.
For the purposes of this tutorial, I’m assuming that the reader already knows:
- How to set up and expose openHAB devices to Google Assistant (typically through myopenhab.org).
- How to record and send IR commands using a controller such as a Broadlink RM4 or Logitech Harmony Hub.
Note: this solution requires that you only control the device through openHAB. If you use the original IR remote or a button on the device, openHAB won’t know about the change and will get out of sync.
Commands
My Rowenta fan’s remote has the following buttons, each with an individual IR code:
- PowerToggle (on/off)
- Silent
- +/- (toggles upward through Low, Medium, and High)
- Turbo
I needed to combine all of these commands into a single item, so that I can tell Google Assistant to “turn on the fan” or “set the fan to silent”. For this to work, openHAB has to know if the fan is currently on/off, and what setting it’s on.
Items
Here are my items in text configuration. You can do this in MainUI if you prefer.
Dimmer Rowenta_Fan "Bedroom Fan" <fan> (Group_HVAC) { ga="Fan" [speeds="0=off,10=silent:one,30=low:two,50=medium:three,70=high:four,90=turbo:five,100=on", lang="en", ordered=true, roomHint="Environment" ]}
Switch Rowenta_Fan_Switch "Power" <fan>
String Rowenta_Fan_Speed "Speed [%s]" <fan>
String Rowenta_Fan_Command "Rowenta Fan" {channel="YOUR_IR_CONTROLLER"}
The only item I interact with is Rowenta_Fan
. It’s a dimmer, because that’s what Google Assistant requires for a fan. I’ve defined numerical fan speeds that represent all of the commands I want to send to the fan (off, silent, low, medium, high, turbo, on).
Note: I’ve spread my commands out from 0-100, but I could also have used 1-7. Google Assistant doesn’t care what the numbers are; it just passes them on to openHAB. If you wanted to, you could have one item that accepts 101 different commands (with 101 corresponding rules).
The Rowenta_Fan_Switch
and Rowenta_Fan_Speed
items are used to store the current power state and setting. I don’t show them in any UIs, as they only need to be updated by rules.
Rules
Whenever Rowenta_Fan
changes, a rule carries out the following activities:
- checks
Rowenta_Fan_Switch
to see if the fan is on/off, and toggles it as necessary - checks
Rowenta_Fan_Speed
and sends the necessary IR commands to get from the current state to the new state (e.g. from Silent to Low) - updates the
Rowenta_Fan_Switch
andRowenta_Fan_Speed
items to the new states
I originally had one big rule with multiple IF and CASE statements to do all of this, but I’ve simplified it into individual rules. It’s easier to replicate in MainUI rules, and easier to debug.
Power off
Since my fan uses the same IR code for on and off, I have to check the current state of the fan. If you have unique IR codes for on and off, you can just send them without needing to check.
rule "Fan Control - Power Off"
when
Item Rowenta_Fan changed to 0
then
//If the fan isn't already off, send the IR command to toggle it
//The IF statement is necessary due to my device using the same IR command for ON and OFF
if (Rowenta_Fan_Switch.state != OFF)
{
Rowenta_Fan_Command.sendCommand("PowerToggle")
}
//Update power status to OFF
Rowenta_Fan_Switch.postUpdate(OFF)
end
Power on
When my Rowenta fan powers on, it automatically returns to its previous setting. This rule accounts for that by updating the Rowenta_Fan
item to match what was saved in Rowenta_Fan_Speed
. If I didn’t do this, Google Assistant and my sitemap would know that the fan is on, but wouldn’t know the current setting.
As with the “Power off” rule, you don’t need to check the state if your device has a unique IR command to turn it on.
rule "Fan Control - Power On"
when
Item Rowenta_Fan changed to 100
then
//If the fan is off, send the IR command to toggle it and update the power status
if (Rowenta_Fan_Switch.state != ON)
{
Rowenta_Fan_Command.sendCommand("PowerToggle")
Rowenta_Fan_Switch.postUpdate(ON)
}
//Update Rowenta_Fan_Speed to previous level
var level = 0
switch (Rowenta_Fan_Speed.state)
{
case "Silent": level = 10
case "Low": level = 30
case "Medium": level = 50
case "High": level = 70
case "Turbo": level = 90
}
Rowenta_Fan.postUpdate(level)
end
Complex IR sequences
Once the fan is turned on, I have to press the +/- button multiple times to toggle through the Low/Medium/High settings of my fan. By checking the current setting (stored in `Rowenta_Fan_Speed), openHAB knows the correct number of IR commands required to get to the new mode. I repeat this for the fan’s Medium and High settings, adjusting the IR sequences accordingly.
This type of rule is necessary whenever the current state of the device determines your IR sequence. You’ll need to map out and test all of your scenarios, and may need to pause between commands so that you don’t overwhelm your device.
rule "Fan Control - Low"
when
Item Rowenta_Fan changed to 30
then
//If the fan is off, send the IR command to toggle it and update the power status
if (Rowenta_Fan_Switch.state != ON)
{
Rowenta_Fan_Command.sendCommand("PowerToggle")
Rowenta_Fan_Switch.postUpdate(ON)
}
//Send the IR commands required to get from the current state to the new state
if (Rowenta_Fan_Speed.state == "Silent" || Rowenta_Fan_Speed.state == "Turbo")
{
Rowenta_Fan_Command.sendCommand("+/-") //first command changes to Medium
Rowenta_Fan_Command.sendCommand("+/-") //second command changes to High
Rowenta_Fan_Command.sendCommand("+/-") //third command changes to Low
}
else if (Rowenta_Fan_Speed.state == "Medium")
{
Rowenta_Fan_Command.sendCommand("+/-") //first command changes to High
Rowenta_Fan_Command.sendCommand("+/-") //second command changes to Low
}
else if (Rowenta_Fan_Speed.state == "High")
{
Rowenta_Fan_Command.sendCommand("+/-") //first command changes to Low
}
Rowenta_Fan_Speed.postUpdate("Low") //update item so that openHAB knows the current state
end
Unique IR commands
The Silent command on my fan has its own IR code, but if my fan is already in Silent mode, a subsequent Silent command will cancel it and revert to whatever state it was previously in. So once again, I check the state before sending the command. You should test all of your IR commands for behaviours like this.
rule "Fan Control - Silent"
when
Item Rowenta_Fan changed to 10
then
//If the fan is off, send the IR command to toggle it and update the power status
if (Rowenta_Fan_Switch.state != ON)
{
Rowenta_Fan_Command.sendCommand("PowerToggle")
Rowenta_Fan_Switch.postUpdate(ON)
}
//If the fan isn't already in Silent mode, send the IR command
if (Rowenta_Fan_Speed.state != "Silent")
{
Rowenta_Fan_Command.sendCommand("SilentNight")
}
//Update Rowenta_Fan_Speed to new setting
Rowenta_Fan_Speed.postUpdate("Silent")
end
That’s a lot of repetitive code
You may have noticed that we’re constantly trying to turn the fan on, which means that this section of code shows up A LOT.
//If the fan is off, send the IR command to toggle it and update the power status
if (Rowenta_Fan_Switch.state != ON)
{
Rowenta_Fan_Command.sendCommand("PowerToggle")
Rowenta_Fan_Switch.postUpdate(ON)
}
It’s not really hurting anything, because these are pretty simple rules. But if you’re bothered by the inefficiency of it all, you can use a lambda. What’s a lambda?
Seriously, that’s an explanation that even I can understand.
If you’re using UI rules, the equivalent would be…umm…well…let’s just ask Rich again.
And with that, I’ve run out of useful information to steal quote from Rich.