Hi everyone,
I was wondering if there is a way not to use the map-file with this binding. I am creating the IR codes for my Daikin air conditioner at runtime using a rule, so I do not want to create a key for each configuration.
rule "AC control"
when Member of AC received command
then
val low_str = '0e0e'
val high_str = '0e2c'
val prefix = "260050020e0e0e0e0e0e0e0e0e0e0d000341713a0e2c0e0e0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e2c0e0e0e2c0e2c0e0e0e2c0e2c0e2c0e2c0e2c0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e2c0e0e0e2c0e0e0e0e0e0e0e2c0e2c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e2c0e2c0e2c0e0e0e2c0e0e0e2c0e2c0d000474713a0e2c0e0e0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e2c0e0e0e2c0e2c0e0e0e2c0e2c0e2c0e2c0e2c0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e2c0e0e0e2c0e0e0e2c0e0e0d000475713a"
val header = "0e2c0e0e0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e2c0e0e0e2c0e2c0e0e0e2c0e2c0e2c0e2c0e2c0e0e0e0e0e2c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e"
val suffix = "0d000d050000000000000000"
var power = AC_power.state()
val mode = AC_mode.state()
val temp_set = AC_set_temp.state()
val wind_level = AC_windlevel.state()
val wind_swing = AC_windswing.state()
val powermode = AC_powermode.state()
val economy = AC_economy.state()
logInfo("broadlink.rules", "State: power "+power+", mode "+mode+", temp "+temp_set+", wind_level "+wind_level + ", wind_swing " + wind_swing + ", powermode " + powermode + ", economy " + economy)
//Integer::parseInt(str,16).intValue()
// Convert to int for checksum: 11 + +da + 27 + 00 + 00
// header
val header_int = Integer.parseInt("11", 16) + Integer.parseInt("da", 16) + Integer.parseInt("27", 16)
var mode_byte_hex = mode.toString
if (mode == NULL){
mode_byte_hex = "0"
postUpdate(AC_mode,0)
}
if (power == ON){
mode_byte_hex += "9"
} else {
mode_byte_hex += "8"
postUpdate(AC_power,OFF)
power = OFF
}
if (power == OFF){
postUpdate(AC_mode_google,"off")
} else if (mode_byte_hex.substring(0,1) == "0"){
postUpdate(AC_mode_google,"heatcool")
} else if (mode_byte_hex.substring(0,1) == "3"){
postUpdate(AC_mode_google,"cool")
} else if (mode_byte_hex.substring(0,1) == "4"){
postUpdate(AC_mode_google,"heat")
} else {
postUpdate(AC_mode_google,"on")
}
val mode_byte_int = Integer.parseInt(mode_byte_hex, 16)
var mode_byte_bin = Integer::toBinaryString(mode_byte_int)
var mode_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < mode_byte_bin.length){
mode_byte_cor += mode_byte_bin.charAt(mode_byte_bin.length-i-1)
} else {
mode_byte_cor += "0"
}
}
mode_byte_bin = String::format("%1$8s", mode_byte_bin)
logInfo("broadlink.rules", "mode_byte_hex "+mode_byte_hex)
logInfo("broadlink.rules", "mode_byte_cor "+mode_byte_cor)
val temp_byte_int = 40
if ((temp_set != null) && (temp_set != NULL)){
temp_byte_int = 2*Integer.parseInt(temp_set.toString)
} else {
postUpdate(AC_set_temp,20)
}
val temp_byte_hex = Integer::toHexString(temp_byte_int)
val temp_byte_bin = Integer::toBinaryString(temp_byte_int)
var temp_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < temp_byte_bin.length){
temp_byte_cor += temp_byte_bin.charAt(temp_byte_bin.length-i-1)
} else {
temp_byte_cor += "0"
}
}
logInfo("broadlink.rules", "temp_byte_hex "+temp_byte_hex)
logInfo("broadlink.rules", "temp_byte_cor "+temp_byte_cor)
val fixed_byte_hex = "00"
val fixed_byte_int = Integer.parseInt(fixed_byte_hex, 16)
val fixed_byte_bin = Integer::toBinaryString(fixed_byte_int)
var fixed_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < fixed_byte_bin.length){
fixed_byte_cor += fixed_byte_bin.charAt(fixed_byte_bin.length-i-1)
} else {
fixed_byte_cor += "0"
}
}
var wind_byte_hex = "a"
if (wind_level == 0){
wind_byte_hex = "a"
} else if (wind_level == 1){
wind_byte_hex = "b"
} else if ((wind_level != null) && (wind_level != NULL)){
wind_byte_hex = wind_level.toString
} else {
postUpdate(AC_windlevel,0)
}
if (wind_swing == ON){
wind_byte_hex += "f"
} else {
wind_byte_hex += "0"
}
val wind_byte_int = Integer.parseInt(wind_byte_hex, 16)
val wind_byte_bin = Integer::toBinaryString(wind_byte_int)
var wind_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < wind_byte_bin.length){
wind_byte_cor += wind_byte_bin.charAt(wind_byte_bin.length-i-1)
} else {
wind_byte_cor += "0"
}
}
logInfo("broadlink.rules", "wind_byte_hex "+wind_byte_hex)
logInfo("broadlink.rules", "wind_byte_cor "+wind_byte_cor)
val timer_a_byte_hex = "00"
val timer_b_byte_hex = "06"
val timer_c_byte_hex = "60"
val timer_a_byte_int = Integer.parseInt(timer_a_byte_hex, 16)
val timer_b_byte_int = Integer.parseInt(timer_b_byte_hex, 16)
val timer_c_byte_int = Integer.parseInt(timer_c_byte_hex, 16)
val timer_a_byte_bin = Integer::toBinaryString(timer_a_byte_int)
val timer_b_byte_bin = Integer::toBinaryString(timer_b_byte_int)
val timer_c_byte_bin = Integer::toBinaryString(timer_c_byte_int)
var timer_a_byte_cor = ""
var timer_b_byte_cor = ""
var timer_c_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < timer_a_byte_bin.length){
timer_a_byte_cor += timer_a_byte_bin.charAt(timer_a_byte_bin.length-i-1)
} else {
timer_a_byte_cor += "0"
}
if (i < timer_b_byte_bin.length){
timer_b_byte_cor += timer_b_byte_bin.charAt(timer_b_byte_bin.length-i-1)
} else {
timer_b_byte_cor += "0"
}
if (i < timer_c_byte_bin.length){
timer_c_byte_cor += timer_c_byte_bin.charAt(timer_c_byte_bin.length-i-1)
} else {
timer_c_byte_cor += "0"
}
}
logInfo("broadlink.rules", "timer_byte_hex "+timer_a_byte_hex + " " +timer_b_byte_hex + " " + timer_c_byte_hex)
logInfo("broadlink.rules", "timer_byte_cor "+timer_a_byte_cor + " " +timer_b_byte_cor + " " + timer_c_byte_cor)
var powermode_byte_hex = "00"
if (powermode == ON){
powermode_byte_hex = "01"
}
val powermode_byte_int = Integer.parseInt(powermode_byte_hex, 16)
val powermode_byte_bin = Integer::toBinaryString(powermode_byte_int)
var powermode_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < powermode_byte_bin.length){
powermode_byte_cor += powermode_byte_bin.charAt(powermode_byte_bin.length-i-1)
} else {
powermode_byte_cor += "0"
}
}
logInfo("broadlink.rules", "powermode_byte_hex "+powermode_byte_hex)
logInfo("broadlink.rules", "powermode_byte_cor "+powermode_byte_cor)
val special_byte_hex = "c1"
val special_byte_int = Integer.parseInt(special_byte_hex, 16)
val special_byte_bin = Integer::toBinaryString(special_byte_int)
var special_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < special_byte_bin.length){
special_byte_cor += special_byte_bin.charAt(special_byte_bin.length-i-1)
} else {
special_byte_cor += "0"
}
}
var economy_byte_hex = "c1"//80
if (economy == ON){
economy_byte_hex = "c1"//84
}
val economy_byte_int = Integer.parseInt(economy_byte_hex, 16)
val economy_byte_bin = Integer::toBinaryString(economy_byte_int)
var economy_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < economy_byte_bin.length){
economy_byte_cor += economy_byte_bin.charAt(economy_byte_bin.length-i-1)
} else {
economy_byte_cor += "0"
}
}
logInfo("broadlink.rules", "economy_byte_hex "+economy_byte_hex)
logInfo("broadlink.rules", "economy_byte_cor "+economy_byte_cor)
val check_byte_int_full = header_int + mode_byte_int+temp_byte_int+wind_byte_int+timer_a_byte_int+timer_b_byte_int+timer_c_byte_int+powermode_byte_int+economy_byte_int
val check_byte_hex_full = Integer::toHexString(check_byte_int_full)
val check_byte_hex = check_byte_hex_full.substring(check_byte_hex_full.length-2,check_byte_hex_full.length)
val check_byte_int = Integer.parseInt(check_byte_hex, 16)
val check_byte_bin = Integer::toBinaryString(check_byte_int)
var check_byte_cor = ""
for (var i = 0; i<8; i++){
if (i < check_byte_bin.length){
check_byte_cor += check_byte_bin.charAt(check_byte_bin.length-i-1)
} else {
check_byte_cor += "0"
}
}
logInfo("broadlink.rules", "check_byte_hex_full "+check_byte_hex_full)
logInfo("broadlink.rules", "check_byte_hex "+check_byte_hex)
logInfo("broadlink.rules", "check_byte_cor "+check_byte_cor)
val command_bin = mode_byte_cor + temp_byte_cor + fixed_byte_cor + wind_byte_cor + fixed_byte_cor + timer_a_byte_cor + timer_b_byte_cor + timer_c_byte_cor + powermode_byte_cor + fixed_byte_cor + economy_byte_cor + fixed_byte_cor + fixed_byte_cor + check_byte_cor
logInfo("broadlink.rules", "command_bin "+command_bin)
logInfo("broadlink.rules", "command_hex "+mode_byte_hex + temp_byte_hex + fixed_byte_hex + wind_byte_hex + fixed_byte_hex + timer_a_byte_hex + timer_b_byte_hex + timer_c_byte_hex + powermode_byte_hex + fixed_byte_hex + economy_byte_hex + fixed_byte_hex + special_byte_hex + check_byte_hex)
val zero = '0'
var control = ""
for (var i = 0; i<command_bin.length; i++){
if (command_bin.substring(i,i+1).equals(zero)){
control += low_str
} else {
control += high_str
}
}
val String commandStr = prefix+header+control+suffix
logInfo("broadlink.rules", "Command send: "+commandStr)
postUpdate(BroadlinkRM3_Command,commandStr)
var String result = executeCommandLine("python /etc/openhab2/scripts/broadlink_cli --type 10178 --host 192.168.1.6 --mac 780f775191f6 --send " +commandStr,10000)
logInfo("broadlink.rules", "python: "+result)
end
if there is a better solution than using a rule, that is welcome too.
Thanks
Edit:
For now I will use “executeCommandLine” as a work around
postUpdate(BroadlinkRM3_Command,commandStr)
var String result = executeCommandLine("python /etc/openhab2/scripts/broadlink_cli --type 10178 --host <ip-address> --mac <mac-address> --send " +commandStr,10000)
using the broadlink github repository by mjg59
Edit (2019-03-24):
I updated the posted rule to the one, which I am using now.
Furthermore the items file including google home integration:
Group AC "Air conditioner"
Group g_AC "Klimaanlage" [ "Thermostat", "Celsius" ]
Switch AC_power "Klimaanlage" (AC)
String AC_mode_google "Modus" (g_AC) [ "homekit:HeatingCoolingMode" ]
String AC_mode "Modus" (AC)
Number AC_cur_temp "Temperatur" (AC, g_AC) [ "CurrentTemperature" ]
Number AC_set_temp "Zieltemperatur" (AC, g_AC) [ "TargetTemperature" ]
Number AC_windlevel "Wind" (AC)
Switch AC_windswing "Windrichtung" (AC)
Switch AC_powermode "Power modus" (AC)
Switch AC_economy "Economy" (AC)
and the relevant part of my sitemap:
Text label="Air Conditioner" icon=aircon
{
Switch item=AC_power label="Power" icon="heating"
Setpoint item=AC_set_temp minValue=18 maxValue=32 step=1 icon="temperature" label="Setpoint [%.0f °C]"
Switch item=AC_mode label="Mode" icon="sofa" mappings=[0="Auto", 2="Dry", 3="Cool", 4="Heat", 6="Fan"]
Switch item=AC_windlevel label="Wind level" icon="fan" mappings=[0="Auto", 1= "Calm", 3="▂", 4="▃", 5="▄", 6="▆", 7="▇"]
Switch item=AC_windswing label="Wind swing" icon="aircon_swing"
Switch item=AC_powermode label="Power mode" icon="wind"
Switch item=AC_economy label="Economy" icon="econmode"
}
and a separate rule to change the mode key which is received from google home to the one used by the airconditioner:
rule "AC Google mode"
when Item AC_mode_google received command
then
var mode = AC_mode_google.state()
if (mode == NULL){
sendCommand(AC_mode, "0")
} else if (mode == "heat"){
postUpdate(AC_power, ON)
sendCommand(AC_mode, "4")
} else if (mode == "cool"){
postUpdate(AC_power, ON)
sendCommand(AC_mode, "3")
} else if (mode == "heatcool"){
postUpdate(AC_power, ON)
sendCommand(AC_mode, "0")
} else if (mode == "on"){
sendCommand(AC_power, ON)
} else if (mode == "off"){
sendCommand(AC_power, OFF)
}
end
Maybe this helps someone else.