├── .gitmodules ├── commands.lua ├── driver.xml └── module └── json.lua /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Control4-HA-Base"] 2 | path = Control4-HA-Base 3 | url = https://github.com/bphillips09/Control4-HA-Base 4 | -------------------------------------------------------------------------------- /commands.lua: -------------------------------------------------------------------------------- 1 | SENT_INITIAL_TEMPERATURE = false 2 | SENT_INITIAL_HUMIDITY = false 3 | 4 | function DRV.OnDriverInit(init) 5 | C4:AddVariable("SENSOR_STATE", "", "STRING") 6 | C4:AddVariable("SENSOR_STATE_INT", "", "INT") 7 | C4:AddVariable("SENSOR_STATE_FLOAT", "", "FLOAT") 8 | C4:AddVariable("SENSOR_LAST_UPDATED", "", "STRING") 9 | end 10 | 11 | function DRV.OnDriverLateInit(init) 12 | OPC.Sensor_Type(Properties["Sensor Type"]) 13 | end 14 | 15 | function DRV.OnDriverDestroyed(init) 16 | end 17 | 18 | function DRV.OnBindingChanged(idBinding, strClass, bIsBound) 19 | if (bIsBound) then 20 | EC.REFRESH() 21 | end 22 | end 23 | 24 | function OPC.Sensor_Type(value) 25 | local isTemp = (value == "Temperature") 26 | local showPropertyValue = 1 27 | if isTemp then showPropertyValue = 0 end 28 | 29 | C4:SetPropertyAttribs("Unit Fallback", showPropertyValue) 30 | 31 | EC.REFRESH() 32 | end 33 | 34 | function OPC.Unit_Fallback() 35 | EC.REFRESH() 36 | end 37 | 38 | function RFP.RECEIEVE_STATE(idBinding, strCommand, tParams) 39 | local jsonData = JSON:decode(tParams.response) 40 | 41 | local stateData 42 | 43 | if jsonData ~= nil then 44 | stateData = jsonData 45 | end 46 | 47 | Parse(stateData) 48 | end 49 | 50 | function RFP.RECEIEVE_EVENT(idBinding, strCommand, tParams) 51 | local jsonData = JSON:decode(tParams.data) 52 | 53 | local eventData 54 | 55 | if jsonData ~= nil then 56 | eventData = jsonData["event"]["data"]["new_state"] 57 | end 58 | 59 | Parse(eventData) 60 | end 61 | 62 | function Parse(data) 63 | if data == nil then 64 | return 65 | end 66 | 67 | if data["entity_id"] ~= EntityID then 68 | return 69 | end 70 | 71 | local sensorType = Properties["Sensor Type"] 72 | 73 | local state = data["state"] 74 | local attributes = data["attributes"] 75 | local lastUpdated = data["last_updated"] 76 | local lastUpdatedStr = tostring(os.date('%Y-%m-%d %H:%M:%S', ParseTime(lastUpdated))) 77 | C4:SetVariable("SENSOR_LAST_UPDATED", lastUpdatedStr) 78 | C4:UpdateProperty("Last Updated", lastUpdatedStr) 79 | 80 | local tParams = {} 81 | 82 | if not Connected then 83 | Connected = true 84 | end 85 | 86 | if state == "unavailable" then 87 | C4:SetVariable("SENSOR_STATE", tostring(state)) 88 | 89 | if sensorType == "Temperature" then 90 | SENT_INITIAL_TEMPERATURE = false 91 | C4:SendToProxy(500, "VALUE_UNAVAILABLE", { STATUS = "offline" }, "NOTIFY") 92 | end 93 | if sensorType == "Humidity" then 94 | SENT_INITIAL_HUMIDITY = false 95 | C4:SendToProxy(600, "VALUE_UNAVAILABLE", { STATUS = "offline" }, "NOTIFY") 96 | end 97 | return 98 | end 99 | 100 | if state ~= nil and state ~= "unavailable" then 101 | local strState = tostring(state) 102 | local numericState = tonumber(state) 103 | 104 | C4:UpdateProperty("Value", strState) 105 | C4:SetVariable("SENSOR_STATE", strState) 106 | 107 | if numericState == nil then 108 | numericState = 0 109 | 110 | C4:SetVariable("SENSOR_STATE_INT", numericState) 111 | C4:SetVariable("SENSOR_STATE_FLOAT", numericState) 112 | else 113 | C4:SetVariable("SENSOR_STATE_INT", math.floor(numericState + 0.5)) 114 | C4:SetVariable("SENSOR_STATE_FLOAT", numericState) 115 | end 116 | 117 | if sensorType == "Temperature" then 118 | local measurement = attributes["unit_of_measurement"] 119 | 120 | local celsiusValue 121 | local fahrenheitValue 122 | 123 | if measurement == "°F" then 124 | fahrenheitValue = numericState 125 | celsiusValue = ToCelsius(fahrenheitValue) 126 | elseif measurement == "°C" then 127 | celsiusValue = numericState 128 | fahrenheitValue = ToFahrenheit(celsiusValue) 129 | else 130 | local unitFallback = Properties["Unit Fallback"] 131 | 132 | if unitFallback == "Fahrenheit" then 133 | fahrenheitValue = numericState 134 | celsiusValue = ToCelsius(fahrenheitValue) 135 | else 136 | celsiusValue = numericState 137 | fahrenheitValue = ToFahrenheit(celsiusValue) 138 | end 139 | end 140 | 141 | if SENT_INITIAL_TEMPERATURE then 142 | tParams = { 143 | CELSIUS = celsiusValue, 144 | FAHRENHEIT = fahrenheitValue, 145 | TIMESTAMP = tostring(os.time()) 146 | } 147 | C4:SendToProxy(500, 'VALUE_CHANGED', tParams, "NOTIFY") 148 | else 149 | SENT_INITIAL_TEMPERATURE = true 150 | 151 | tParams = { 152 | STATUS = "active", 153 | TIMESTAMP = tostring(os.time()) 154 | } 155 | C4:SendToProxy(500, 'VALUE_INITIALIZE', tParams, "NOTIFY") 156 | if measurement == "°F" then 157 | fahrenheitValue = numericState 158 | celsiusValue = ToCelsius(fahrenheitValue) 159 | elseif measurement == "°C" then 160 | celsiusValue = numericState 161 | fahrenheitValue = ToFahrenheit(celsiusValue) 162 | end 163 | tParams = { 164 | CELSIUS = celsiusValue, 165 | FAHRENHEIT = fahrenheitValue, 166 | TIMESTAMP = tostring(os.time()) 167 | } 168 | C4:SendToProxy(500, 'VALUE_CHANGED', tParams, "NOTIFY") 169 | end 170 | elseif sensorType == "Humidity" then 171 | if SENT_INITIAL_HUMIDITY then 172 | tParams = { 173 | SCALE = "FAHRENHEIT", 174 | VALUE = numericState, 175 | TIMESTAMP = tostring(os.time()) 176 | } 177 | 178 | C4:SendToProxy(600, 'VALUE_CHANGED', tParams, "NOTIFY") 179 | else 180 | SENT_INITIAL_HUMIDITY = true 181 | 182 | tParams = { 183 | STATUS = "active", 184 | TIMESTAMP = tostring(os.time()) 185 | } 186 | 187 | C4:SendToProxy(600, 'VALUE_INITIALIZE', tParams, "NOTIFY") 188 | end 189 | end 190 | end 191 | end 192 | -------------------------------------------------------------------------------- /driver.xml: -------------------------------------------------------------------------------- 1 | 2 | BP 3 | BP 4 | BP 5 | HA Generic Sensor 6 | HA Generic Sensor 7 | 09/10/2023 12:00 8 | 05/02/2024 12:00 9 | 110 10 | lua_gen 11 | IP 12 | DriverWorks 13 | true 14 | 15 | Experience Button 16 | 17 | 18 |