Hi
You really don’t have many options to solve the problem.
- install Homebridge(HB) + plugin @0x5e/homebridge-tuya-platform (for cloud only)
- install in OpenHab (OH) - Smarthome/J Tuya (only for local devices)
then you can read the data:
a) from HB via API
b) from HB via OH if you install the LogReader AddOn for OH
c) install Home Assistant (HA) and connect HB to HA
I use 1 a) for Thermostatic valve, Temperature Humidity Sensor, Contact Sensor.
The following procedure is applicable to all who use Homebridge and OpenHab:
- install Homebridge
Homebridge
for example to an existing OpenHAB installation:
then install plugin @0x5e/homebridge-tuya-platform into HB:
more detailed instructions:
set parameters for communication with Tuya cloud
other HB settings:
- Settings
- General
-UI Settings
-Advanced
-Login Settings
-Homebridge UI Authentication
– switch the setting to None
(this setting will allow you to get an Access Token for access to the HB API)
if you want a more detailed Log, in the settings:
-Log Settings
– set Enable
Restart HB
- in OH create:
-
Items (only Homebridge Token Group is enough to start)
-
use Rule
HB_NEW_TOKEN
HBAPI_DATA_UPDATE (you will not use the Rule part from
if(HB_… the rest is not needed yet)
-
Use the line so that the Rule writes the entire JSON as a response from HB to the Log
logInfo(“HB_TH_STATE.rules”, test )
-
copy the contents of the JSON from Log
only the part between [{“aid”:1,“iid”:…]
-
paste the copied into the left window on the page
https://jsonpathfinder.com/
-
in the right window you will see all the items that you can load or use in OH as Items
-
select values that are interesting or necessary and edit Rule HB_TH_STATE and Items file.
- edit the Rule
HB_TH_STATE
(add part if(HB_… to END
- according to the JSON content, map the values in “[0-x].values.XYZ” according to the actual positions in the JSON
- each line in the Rule interprets one loaded item from the Items file, for example: HB_th_k_cs.postUpdate(transform(“JSONPATH”, “$.[1].values.CurrentHeatingCoolingState”, test))
- edit the Rule as needed
HB_ALARM_MODE (loads a new Access Token when it expires)
HBAPI_DATA_UPDATE (changes the Tuya device setting value according to your setting in OH)
Items:
Group gBA "XYZ" ["Location"]
Group gBA_I "XYZ" (gBA) ["Location"]
Group gBA_D "XYZ" (gBA) ["Location"]
Group gBA_A "XYZ" (gBA) ["Location"]
Group gBA_O "XYZ" (gBA) ["Location"]
Group gBA_K "XYZ" (gBA) ["Location"]
Group:Number:SUM gBA_S "Contact state" (gBA) ["Control"]
Group gHB_T "Homebridge Token" (gBA) ["Control"]
String HB_access_token "HB Access Token" (gHB_T)
String HB_token_type "HB Token type" (gHB_T)
Number HB_expires_in "HB Expires in" (gHB_T)
Number HB_expires_alarm "HB alarm" (gHB_T)
String HB_model "HB Model type" (gHB_T)
Group gHB_TK "Thermostat K" <heating> (gBA_K) ["RadiatorControl"]
Number HB_th_k_cs "K Mod Curr" <settings> (gHB_TK) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_k_ts "K Mod Targ" <settings> (gHB_TK) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_k_ct "K Temp Curr" <temperature> (gHB_TK) ["Temperature","Measurement"] { stateDescription=" " [ pattern= "%.1f °C" ]}
Number HB_th_k_tt "K Temp Targ" <temperature> (gHB_TK) ["Temperature","Setpoint"] { stateDescription=" " [ pattern= "%d °C" ]}
Number HB_th_k_sa "K Thermostat onLine" <network> (gHB_TK) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
String HB_th_k_uuid "K UUID" <text> (gHB_TK) ["Status"]
String HB_th_k_name "K TH name " <text> (gHB_TK) ["Status"]
Group gHB_OK "Win K" <window> (gBA_K) ["Window"]
Number HB_cn_k_sb "K X LowBat" <lowbattery> (gHB_OK) ["LowBattery"] { stateDescription=" " [ pattern= "%s-BattAlarm" ]}
Number HB_cn_k_bl "K X BatLevel" <batterylevel> (gHB_OK) ["Battery"] { stateDescription=" " [ pattern= "%d %%" ]}
Number HB_cn_k_sa "K X onLine" <network> (gHB_OK) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
Contact HB_cn_k_ss "K Win State" <Window> (gHB_OK, gBA_S) ["Opening","OpenState"]
Group gHB_TI "Thermostat I" <heating> (gBA_I) ["RadiatorControl"]
Number HB_th_i_cs "I Mod Curr." <settings> (gHB_TI) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_i_ts "I Mod Targ" <settings> (gHB_TI) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_i_ct "I Temp Curr" <temperature> (gHB_TI) ["Temperature","Measurement"] { stateDescription=" " [ pattern= "%.1f °C" ]}
Number HB_th_i_tt "I Temp Targ" <temperature> (gHB_TI) ["Temperature","Setpoint"] { stateDescription=" " [ pattern= "%d °C" ]}
Number HB_th_i_sa "I Thermostat onLine" <network> (gHB_TI) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
String HB_th_i_uuid "I UUID" <text> (gHB_TI) ["Status"]
String HB_th_i_name "I TH name " <text> (gHB_TI) ["Status"]
Group gHB_OI "Win I" <window> (gBA_I) ["Window"]
Number HB_cn_i_sb "I X LowBat" <lowbattery> (gHB_OI) ["LowBattery"] { stateDescription=" " [ pattern= "%s-BattAlarm" ]}
Number HB_cn_i_bl "I X BatLevel" <batterylevel> (gHB_OI) ["Battery"] { stateDescription=" " [ pattern= "%d %%" ]}
Number HB_cn_i_sa "I X onLine" <network> (gHB_OI) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
Contact HB_cn_i_ss "I Win State" <Window> (gHB_OI, gBA_S) ["Opening","OpenState"]
Group gHB_TA "Thermostat A" <heating> (gBA_A) ["RadiatorControl"]
Number HB_th_a_cs "A Mod Curr" <settings> (gHB_TA) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_a_ts "A Mod Targ" <settings> (gHB_TA) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_a_ct "A Temp Curr" <temperature> (gHB_TA) ["Temperature","Measurement"] { stateDescription=" " [ pattern= "%.1f °C" ]}
Number HB_th_a_tt "A Temp Targ" <temperature> (gHB_TA) ["Temperature","Setpoint"] { stateDescription=" " [ pattern= "%d °C" ]}
Number HB_th_a_sa "A Thermostat onLine" <network> (gHB_TA) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
String HB_th_a_uuid "A UUID" <text> (gHB_TA) ["Status"]
String HB_th_a_name "A TH name " <text> (gHB_TA) ["Status"]
Group gHB_OA "Win A" <window> (gBA_A) ["Window"]
Number HB_cn_a_sb "A X LowBat" <lowbattery> (gHB_OA) ["LowBattery"] { stateDescription=" " [ pattern= "%s-BattAlarm" ]}
Number HB_cn_a_bl "A X BatLevel" <batterylevel> (gHB_OA) ["Battery"] { stateDescription=" " [ pattern= "%d %%" ]}
Number HB_cn_a_sa "A X onLine" <network> (gHB_OA) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
Contact HB_cn_a_ss "A Win State" <Window> (gHB_OA, gBA_S) ["Opening","OpenState"]
Group gHB_TD "Thermostat D" <heating> (gBA_D) ["RadiatorControl"]
Number HB_th_d_cs "D Mod Curr" <settings> (gHB_TD) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_d_ts "D Mod Targ" <settings> (gHB_TD) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=Off,1=Heat,2=Cool,3=Auto" ]}
Number HB_th_d_ct "D Temp Curr" <temperature> (gHB_TD) ["Temperature","Measurement"] { stateDescription=" " [ pattern= "%.1f °C" ]}
Number HB_th_d_tt "D Temp Targ" <temperature> (gHB_TD) ["Temperature","Setpoint"] { stateDescription=" " [ pattern= "%d °C" ]}
Number HB_th_d_sa "D Thermostat onLine" <network> (gHB_TD) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
String HB_th_d_uuid "D UUID" <text> (gHB_TD) ["Status"]
String HB_th_d_name "D TH name " <text> (gHB_TD) ["Status"]
Group gHB_OD "Door D" <window> (gBA_D) ["Window"]
Number HB_cn_d_sb "D X LowBat" <lowbattery> (gHB_OD) ["LowBattery"] { stateDescription=" " [ pattern= "%s-BattAlarm" ]}
Number HB_cn_d_bl "D X BatLevel" <batterylevel> (gHB_OD) ["Battery"] { stateDescription=" " [ pattern= "%d %%" ]}
Number HB_cn_d_sa "D X onLine" <network> (gHB_OD) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
Contact HB_cn_d_ss "D Win State" <Window> (gHB_OD, gBA_S) ["Opening","OpenState"]
Group gHB_DO "Door O" <door> (gBA_O) ["Door"]
Number HB_cn_o_sb "O X LowBat" <lowbattery> (gHB_DO) ["LowBattery"] { stateDescription=" " [ pattern= "%s-BattAlarm" ]}
Number HB_cn_o_bl "O X BatLevel" <batterylevel> (gHB_DO) ["Battery"] { stateDescription=" " [ pattern= "%d %%" ]}
Number HB_cn_o_sa "O X onLine" <network> (gHB_DO) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
Contact HB_cn_o_ss "O Door State" <Door> (gHB_DO, gBA_S) ["Opening","OpenState"]
Group gHB_SO "Sens O" <sofa> (gBA_O) ["Sensor"]
Number HB_se_b_sb "O X LowBat" <lowbattery> (gHB_SO) ["LowBattery"] { stateDescription=" " [ pattern= "%s-BattAlarm" ]}
Number HB_se_b_bl "O X BatLevel" <batterylevel> (gHB_SO) ["Battery"] { stateDescription=" " [ pattern= "%d %%" ]}
Number HB_se_b_sa "O X onLine" <network> (gHB_SO) ["Status"] { stateDescription=" " [ pattern= "%s", options="0=OFFLINE,1=ONLINE"]}
Number HB_se_t_ct "O Temp" <temperature> (gHB_SO) ["Temperature","Measurement"] { stateDescription=" " [ pattern= "%.1f °C" ]}
Number HB_se_h_ch "O Hum" <humidity> (gHB_SO) ["Humidity","Measurement"] { stateDescription=" " [ pattern= "%.1f %%" ] }
rule "HB_NEW_TOKEN"
when
System started or
Item HB_expires_alarm changed to 1
then
val cmnd = "/usr/bin/curl -s -X POST http://192.168.1.XX:8581/api/auth/noauth"
var result = executeCommandLine(Duration.ofSeconds(1), "/bin/sh", "-c", cmnd)
HB_access_token.postUpdate(transform("JSONPATH", "$.access_token", result))
HB_token_type.postUpdate(transform("JSONPATH", "$.token_type", result))
HB_expires_in.postUpdate(transform("JSONPATH", "$.expires_in", result))
end
rule "HB_ALARM_MODE"
when
Item HB_model changed
then
if (HB_model.state.toString != "homebridge") {
logInfo("HB_ALARM_MODE.rules - DATA BROKEN ALARM: ", HB_model.state.toString)
HB_expires_alarm.postUpdate(1)
}
else {
logInfo("HB_ALARM_MODE.rules - DATA OK:", HB_model.state.toString)
HB_expires_alarm.postUpdate(0)
}
end
rule "HB_TH_STATE"
when
//Item HB_th_a_tt changed or
//Item HB_th_d_tt changed or
//Item HB_th_i_tt changed or
Item HB_th_k_tt changed
then
val link = "'http://192.168.1.XX:8581/api/accessories/" + HB_th_k_uuid.state.toString +"'"
val headers = " -H 'Authorization: Bearer " + HB_access_token.state.toString +"'"
val headers2 = " -H 'Content-Type: application/json'"
val json = "'{\"characteristicType\": \"TargetTemperature\",\"value\": " + HB_th_k_tt.state.toString +"}'"
val curlcommand = "/usr/bin/curl -s -X PUT " + link + headers + headers2 + " -d " + json
var String test = executeCommandLine(Duration.ofSeconds(1), "/bin/sh", "-c", curlcommand)
logInfo("HB_TH_STATE.rules", "Thermostat set: " + HB_th_k_tt.state )
end
rule "HBAPI_DATA_UPDATE"
when
//Time cron "0 0/1 * 1/1 * ? *" //1 min
//Time cron "0/30 0/1 * 1/1 * ? *" //30 sec
Time cron "0/15 0/1 * 1/1 * ? *" //15 sec
//Time cron "0/10 * * ? * *" //10 sec
then
val link = 'http://192.168.1.XX:8581/api/accessories'
val headers = " -H 'Authorization: Bearer " + HB_access_token.state.toString +"'"
val curlcommand = "/usr/bin/curl -s -X GET " + link + headers
var String test = executeCommandLine(Duration.ofSeconds(1), "/bin/sh", "-c", curlcommand)
//logInfo("HB_TH_STATE.rules", test )
if (HB_expires_alarm.state == 0) {
//Model info
HB_model.postUpdate(transform("JSONPATH", "$.[0].accessoryInformation.Model", test))
//K Thermostat
HB_th_k_cs.postUpdate(transform("JSONPATH", "$.[1].values.CurrentHeatingCoolingState", test))
HB_th_k_ts.postUpdate(transform("JSONPATH", "$.[1].values.TargetHeatingCoolingState", test))
HB_th_k_ct.postUpdate(transform("JSONPATH", "$.[1].values.CurrentTemperature", test))
HB_th_k_tt.postUpdate(transform("JSONPATH", "$.[1].values.TargetTemperature", test))
HB_th_k_sa.postUpdate(transform("JSONPATH", "$.[1].values.StatusActive", test))
HB_th_k_uuid.postUpdate(transform("JSONPATH", "$.[1].uniqueId", test))
HB_th_k_name.postUpdate(transform("JSONPATH", "$.[1].serviceName", test))
//K Contact
HB_cn_k_sb.postUpdate(transform("JSONPATH", "$.[5].values.StatusLowBattery", test))
HB_cn_k_bl.postUpdate(transform("JSONPATH", "$.[5].values.BatteryLevel", test))
HB_cn_k_sa.postUpdate(transform("JSONPATH", "$.[5].values.StatusActive", test))
val k_ss = transform("JSONPATH", "$.[6].values.ContactSensorState", test)
if (k_ss == "0"){ HB_cn_k_ss.postUpdate(CLOSED) } else { HB_cn_k_ss.postUpdate(OPEN) }
//O THsensor
HB_se_b_sb.postUpdate(transform("JSONPATH", "$.[2].values.StatusLowBattery", test))
HB_se_b_bl.postUpdate(transform("JSONPATH", "$.[2].values.BatteryLevel", test))
HB_se_b_sa.postUpdate(transform("JSONPATH", "$.[2].values.StatusActive", test))
HB_se_t_ct.postUpdate(transform("JSONPATH", "$.[3].values.CurrentTemperature", test))
HB_se_h_ch.postUpdate(transform("JSONPATH", "$.[4].values.CurrentRelativeHumidity", test))
//I Thermostat
HB_th_i_cs.postUpdate(transform("JSONPATH", "$.[7].values.CurrentHeatingCoolingState", test))
HB_th_i_ts.postUpdate(transform("JSONPATH", "$.[7].values.TargetHeatingCoolingState", test))
HB_th_i_ct.postUpdate(transform("JSONPATH", "$.[7].values.CurrentTemperature", test))
HB_th_i_tt.postUpdate(transform("JSONPATH", "$.[7].values.TargetTemperature", test))
HB_th_i_sa.postUpdate(transform("JSONPATH", "$.[7].values.StatusActive", test))
HB_th_i_uuid.postUpdate(transform("JSONPATH", "$.[7].uniqueId", test))
HB_th_i_name.postUpdate(transform("JSONPATH", "$.[7].serviceName", test))
//I Contact
HB_cn_i_sb.postUpdate(transform("JSONPATH", "$.[8].values.StatusLowBattery", test))
HB_cn_i_bl.postUpdate(transform("JSONPATH", "$.[8].values.BatteryLevel", test))
HB_cn_i_sa.postUpdate(transform("JSONPATH", "$.[8].values.StatusActive", test))
val i_ss = transform("JSONPATH", "$.[9].values.ContactSensorState", test)
if (i_ss == "0"){ HB_cn_i_ss.postUpdate(CLOSED) } else { HB_cn_i_ss.postUpdate(OPEN) }
//A Thermostat
HB_th_a_cs.postUpdate(transform("JSONPATH", "$.[12].values.CurrentHeatingCoolingState", test))
HB_th_a_ts.postUpdate(transform("JSONPATH", "$.[12].values.TargetHeatingCoolingState", test))
HB_th_a_ct.postUpdate(transform("JSONPATH", "$.[12].values.CurrentTemperature", test))
HB_th_a_tt.postUpdate(transform("JSONPATH", "$.[12].values.TargetTemperature", test))
HB_th_a_sa.postUpdate(transform("JSONPATH", "$.[12].values.StatusActive", test))
HB_th_a_uuid.postUpdate(transform("JSONPATH", "$.[12].uniqueId", test))
HB_th_a_name.postUpdate(transform("JSONPATH", "$.[12].serviceName", test))
//A Contact
HB_cn_a_sb.postUpdate(transform("JSONPATH", "$.[10].values.StatusLowBattery", test))
HB_cn_a_bl.postUpdate(transform("JSONPATH", "$.[10].values.BatteryLevel", test))
HB_cn_a_sa.postUpdate(transform("JSONPATH", "$.[10].values.StatusActive", test))
val a_ss = transform("JSONPATH", "$.[11].values.ContactSensorState", test)
if (a_ss == "0"){ HB_cn_a_ss.postUpdate(CLOSED) } else { HB_cn_a_ss.postUpdate(OPEN) }
//D Thermostat
HB_th_d_cs.postUpdate(transform("JSONPATH", "$.[13].values.CurrentHeatingCoolingState", test))
HB_th_d_ts.postUpdate(transform("JSONPATH", "$.[13].values.TargetHeatingCoolingState", test))
HB_th_d_ct.postUpdate(transform("JSONPATH", "$.[13].values.CurrentTemperature", test))
HB_th_d_tt.postUpdate(transform("JSONPATH", "$.[13].values.TargetTemperature", test))
HB_th_d_sa.postUpdate(transform("JSONPATH", "$.[13].values.StatusActive", test))
HB_th_d_uuid.postUpdate(transform("JSONPATH", "$.[13].uniqueId", test))
HB_th_d_name.postUpdate(transform("JSONPATH", "$.[13].serviceName", test))
//D Win
HB_cn_d_sb.postUpdate(transform("JSONPATH", "$.[14].values.StatusLowBattery", test))
HB_cn_d_bl.postUpdate(transform("JSONPATH", "$.[14].values.BatteryLevel", test))
HB_cn_d_sa.postUpdate(transform("JSONPATH", "$.[14].values.StatusActive", test))
val d_ss = transform("JSONPATH", "$.[15].values.ContactSensorState", test)
if (d_ss == "0"){ HB_cn_d_ss.postUpdate(CLOSED) } else { HB_cn_d_ss.postUpdate(OPEN) }
//O Contact
HB_cn_o_sb.postUpdate(transform("JSONPATH", "$.[16].values.StatusLowBattery", test))
HB_cn_o_bl.postUpdate(transform("JSONPATH", "$.[16].values.BatteryLevel", test))
HB_cn_o_sa.postUpdate(transform("JSONPATH", "$.[16].values.StatusActive", test))
val o_ss = transform("JSONPATH", "$.[17].values.ContactSensorState", test)
if (o_ss == "0"){ HB_cn_o_ss.postUpdate(CLOSED) } else { HB_cn_o_ss.postUpdate(OPEN) }
logInfo("HBAPI_DATA_UPDATE.rules", "Data Ok" )
}
else {
HB_expires_alarm.postUpdate(0)
logInfo("HBAPI_DATA_UPDATE.rule - ALARM DATA NOT READ RESET ALARM:", HB_expires_alarm.state.toString)
}
end
it’s not that complicated…