- Location:
- /trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
/trunk/L_VeraConnectWWN1.lua
r1 r3 1 1 module("L_VeraConnectWWN1", package.seeall) 2 3 require("socket") 4 local ssl = require("ssl") 5 local peer = socket.tcp() 6 local params = { 7 mode = "client", 8 protocol = "tlsv1", 9 verify = {"none"}, 10 options = {"no_compression"}, 11 ciphers = "ALL", 12 } 13 2 -- andrei : {"access_token":"c.CzL215BijVuzFgznRCW9QKvA0eblyxSMI9ad7klSX87vkpDyI0XxiftueUPWqDim9ejCCrYJ9r0WCHhJz16clWAxoLTqhcbXeYT45kzbeJ8gC5UwLIxdrc0v2teyuVhnSz6ZLmTJ2TEqEXIm","expires_in":315360000} 3 -- florin : {"access_token":"c.7zKZ8yzOgDWUKGUTeBKz1JOPRAM6uWOse7Eb6jnfcKTT23hyOLKV5pv3vafKRp6wHlRHkVjknRABDa4NKnxAJNl6lq4GIoJPXIX4mby3ubcMprxqrM2GFN0EGb2WdWQwtsTblXLVgkKvGG2Y","expires_in":315360000} 4 5 --require("socket") 6 local ltn12 = require("ltn12") 7 local dkjson = require ("dkjson") 8 local https = require("ssl.https") 9 local http = require ("socket.http") 10 --local mime = require("mime") 14 11 -- Flags 15 12 local DEBUG_MODE = false 16 13 local FLAGS = { 17 PARTITIONS = false, 18 ZONES = true 14 19 15 } 20 16 … … 23 19 TEMPERATURE_SENSOR = "D_TemperatureSensor1.xml", 24 20 THERMOSTAT = "D_HVAC_ZoneThermostat1.xml", 25 SMOKE_SENSOR = "D_SmokeSensor1.xml" 21 HUMIDITY = "D_HumiditySensor1.xml", 22 SMOKE_SENSOR = "D_SmokeSensor1.xml", 23 BINARY_LIGHT = "D_BinaryLight1.xml" 26 24 } 27 25 … … 29 27 TEMPERATURE_SENSOR = "urn:schemas-micasaverde-com:device:TemperatureSensor:1", 30 28 THERMOSTAT = "urn:schemas-upnp-org:device:HVAC_ZoneThermostat:1", 31 SMOKE_SENSOR = "urn:schemas-micasaverde-com:device:SmokeSensor:1" 29 HUMIDITY = "urn:schemas-micasaverde-com:device:HumiditySensor:1", 30 SMOKE_SENSOR = "urn:schemas-micasaverde-com:device:SmokeSensor:1", 31 BINARY_LIGHT = "urn:schemas-upnp-org:device:BinaryLight:1" 32 32 } 33 33 … … 55 55 -- LastUpdate 56 56 local DISPLAY_SECONDS = 20 57 local POLLING_RATE = 10 --5 -- 30 --"PollFrequency"57 local POLLING_RATE = 5 -- 30 --"PollFrequency" 58 58 59 59 -- Globals … … 61 61 local lug_device = nil 62 62 local g_appendPtr -- The pointer passed to luup.chdev.append 63 local g_pinCodes = {}64 63 local g_taskHandle = -1 65 local g_errorMessage = nil66 64 local g_lastTask = os.time() -- The time when the status message was last updated. 67 local g_users = nil 68 local g_areas = { 65 local g_username = "" 66 local g_password = "" 67 local g_fileSize = 0 68 local g_maxFileSize = 5 * 1024 * 1024 69 local g_thermostats = { 69 70 -- .panelID = "" 70 71 -- .name = "" 71 72 -- .devId 72 73 } 74 local g_smoke = { 75 76 } 77 local g_structures = { 78 79 } 73 80 74 81 local ipAddress 75 82 local ipPort 76 83 local NEST_UA = "Nest/1.1.0.10 CFNetwork/548.0.4" 84 local nest_token = "" 85 local nest_ClientID = "5b1585a5-b64e-4759-903e-895ac9373245" 86 local nest_Secret = "noR9PTaBOHx6kONdieaClyyBX" 87 local g_URL = "https://developer-api.nest.com" 88 local temperatureScale = "" 89 -- 7W69Q34L 77 90 --------------------------------------------------------- 78 91 -----------------Generic Utils--------------------------- … … 100 113 g_lastTask = os.time() 101 114 luup.call_delay("clearTask", DISPLAY_SECONDS) 102 end103 104 105 local function wait(peer, err)106 if err == "timeout" or err == "wantread" then107 --log("***WANTREAD***")108 socket.select({peer}, nil,0)109 elseif err == "wantwrite" then110 --log("***WANTWRITE***")111 socket.select(nil, {peer},0)112 else113 --peer:close()114 --os.exit(1)115 end116 end117 118 local function send(str, peer)119 local match = {"0","1","2","3","4","5","6","7","8","9"}120 local length = tostring(str:len())121 local tosend = fromhex("01")122 123 for _,v in pairs(match) do124 if v == length then125 length = string.format('%02s',length)126 end127 end128 129 tosend = tosend .. fromhex(length) .. str130 debug("(Bosch Plugin)::(send) : Sending...")131 peer:settimeout(0.3)132 local succ, err = peer:send(tosend)133 debug("(Bosch Plugin)::(send) : Waiting...")134 wait(peer, err)135 if succ then136 debug("(Bosch Plugin)::(send) : Succesifully sent : [".. tohex(tosend) .. "] with length = [" .. succ .. "]")137 else138 debug("(Bosch Plugin)::(send) : Sending error!!! .. Reconnecting ... ")139 reconnect()140 if err then141 debug("(Bosch Plugin)::(send) : ERROR : " .. err)142 end143 end144 end145 146 local function receive()147 local data = nil148 local status149 local partials = nil150 local length = 0151 local start = os.time()152 local stop153 while (not partials) or (tostring(partials) == "") do154 data , status, partials = peer:receive()155 stop = os.time()156 if (stop - start) > 10 then157 debug("partial = [" .. tostring(partial) .. "]")158 debug("status = [" .. tostring(status) .. "]")159 debug("data = [" .. tostring(data) .. "]")160 return161 end162 end163 164 return partials165 end166 167 local function login()168 -- debug("in login()")169 170 local data = readSettings()171 172 -- if there is no username or password, then no matter what, don't proceed173 if (data.username == "" or data.password == "") then174 task("Please specify username and password.")175 clearSession()176 return177 end178 179 -- if there is old session data, it might still be good, so try it!180 if (data.transport_url ~= "" and data.userid ~= "" and data.access_token ~= "") then181 debug("assuming saved login credentials are still valid.")182 return data183 end184 185 -- perform https POST to nest.com to login186 local res = {}187 local body = urlcode.encodetable{username = data.username, password = data.password}188 local headers = {["user-agent"] = NEST_UA,189 ["content-length"] = string.len(body),190 ["content-type"] = "application/x-www-form-urlencoded"}191 local url = { url = "https://home.nest.com/user/login",192 protocol = "tlsv1",193 method = "POST",194 source = ltn12.source.string(body),195 sink = ltn12.sink.table(res),196 headers = headers }197 198 local one, code, headers, status = https.request(url)199 200 if (code == 200) then201 res = json.decode(table.concat(res))202 203 data.transport_url = res.urls.transport_url204 data.userid = res.userid205 data.access_token = res.access_token206 207 task("Successful nest.com login.", TASK_SUCCESS)208 saveSession(data.transport_url, data.userid, data.access_token)209 return data210 else211 task("Failed to login: code=" .. tostring(code) .. ", status=" .. tostring(status))212 clearSession()213 end214 end215 216 local function getPackageVersion()217 debug("getPackageVersion", "Verifying packages...")218 local REQUIRED_VERSION = { '1', '0', '1', 'e', '1' }219 local stdout = io.popen("opkg list-installed | awk '/openssl-util/ {print $3}'")220 local version = stdout:read("*a")221 version = version:match("([^%s]+)")222 stdout:close()223 local i = 1224 for c in version:gmatch("[^.-]") do225 if c < REQUIRED_VERSION[i] then226 os.execute ("opkg install 'http://downloads.openwrt.org/attitude_adjustment/12.09/ramips/rt3883/packages/openssl-util_1.0.1e-1_ramips.ipk'")227 debug("(Bosch Plugin)::(getPackageVersion) : Updating openssl-util!!!")228 end229 i = i + 1230 end231 REQUIRED_VERSION = { '0', '5', '5'}232 stdout = io.popen("opkg list-installed | awk '/luasec/ {print $3}'")233 version = stdout:read("*a")234 version = version:match("([^%s]+)")235 stdout:close()236 i = 1237 for c in version:gmatch("[^.-]") do238 if c < REQUIRED_VERSION[i] then239 os.execute ("opkg update")240 os.execute ("opkg install luasec")241 debug("(Bosch Plugin)::(getPackageVersion) : Updating luasec!!!")242 end243 i = i + 1244 end245 REQUIRED_VERSION = { '1', '0', '1', 'g', '1' }246 stdout = io.popen("opkg list-installed | awk '/libopenssl/ {print $3}'")247 version = stdout:read("*a")248 version = version:match("([^%s]+)")249 stdout:close()250 i = 1251 for c in version:gmatch("[^.-]") do252 if c < REQUIRED_VERSION[i] then253 os.execute ("opkg install 'http://downloads.openwrt.org/attitude_adjustment/12.09/ramips/rt3883/packages/libopenssl_1.0.1g-1_ramips.ipk'")254 debug("(Bosch Plugin)::(getPackageVersion) : Updating libopenssl!!!")255 end256 i = i + 1257 end258 debug("(Bosch Plugin)::(getPackageVersion) : Packages OK")259 115 end 260 116 … … 266 122 return s 267 123 end 124 125 local function getTemperatureScale() 126 local code, data = luup.inet.wget("http://localhost:3480/data_request?id=lu_sdata") 127 if (code == 0) then 128 data = dkjson.decode(data) 129 end 130 temperatureScale = ((code == 0) and (data ~= nil) and (data.temperature ~= nil)) and string.lower(data.temperature) or "f" 131 end 132 133 local function getNestDeviceID(device, data_structure) 134 for k,v in pairs (data_structure) do 135 if v.vera_id == device then 136 return v.device_id 137 end 138 end 139 return 140 end 141 142 local function nestRequest(method, headers, URL, data) 143 --debug("nestRequest","method = " .. method) 144 --debug("nestRequest","headers = " .. tostring(headers)) 145 --debug("nestRequest","URL = " .. URL) 146 --debug("nestRequest","URL = " .. URL) 147 local curlCommand = "" 148 if method == "GET" or method == "POST" then 149 curlCommand = "curl -k -L -X " .. method .. " " .. headers .. " " .. URL 150 elseif method == "STREAM" then 151 curlCommand = "curl -N -k -v -L " .. URL .. " " .. headers .. " > /tmp/NestOutput.txt &" 152 else 153 curlCommand = "curl -k -v -L -X " .. method .. " " .. URL .. " " .. headers .. " " .. data 154 end 155 --debug("nestRequest", "curlCommand = " .. tostring(curlCommand)) 156 local stdout = io.popen(curlCommand) 157 local response = stdout:read("*a") 158 stdout:close() 159 --debug("nestRequest", "curlCommand Response = [" .. tostring(response) .. "]") 160 161 if method == "STREAM" then 162 local fileCreated = io.open("/tmp/NestOutput.txt") 163 if fileCreated then 164 return true 165 else 166 return 167 end 168 end 169 170 if response and response ~= "" then 171 local json_string = response 172 local json_response = dkjson.decode(response) 173 local data = {} 174 if json_response.error then 175 debug("nestRequest", "error = " .. tostring(json_response.error)) 176 debug("nestRequest", "description = " .. tostring(json_response.error_description)) 177 return 178 else 179 return json_response, json_string 180 end 181 --[[ 182 for k,v in pairs(response) do 183 log("get_token","key = [" .. tostring(k) .. "] and value = [" .. v .. "]") 184 end 185 -- ]] 186 return response 187 else 188 debug("nestRequest", "Empty response!") 189 return 190 end 191 end 192 193 local function get_token() 194 end 195 196 local function clearNestOutputFile() 197 local stdout = io.popen("ps | grep 'curl -N -k -v -L https://developer-api.nest.com/devices.json?auth=' | grep -v 'grep'") 198 local response = stdout:read("*a") 199 stdout:close() 200 response = response:gmatch("(%d+) root") 201 for v in response do 202 debug("clearNestOutputFile", "Killed process " .. v) 203 os.execute("kill " .. v) 204 end 205 os.execute("rm /tmp/NestOutput.txt") 206 end 207 208 local function startStreaming() 209 clearNestOutputFile() 210 local url = g_URL .. "/devices.json?auth=" .. nest_token 211 local header = "-H \"Accept: text/event-stream\" " 212 local response, response_string = nestRequest("STREAM", header, url, "") 213 if response then 214 debug("startStreaming", "Streaming started successful!") 215 else 216 --debug("startStreaming", "Nest Data = " .. response_string) 217 debug("startStreaming", "ERROR : Could not start Stream!") 218 end 219 end 220 221 function getStreamEvents() 222 debug("getStreamEvents", "Getting Stream Events ...") 223 local lfs = require "lfs" 224 local fileSize = lfs.attributes("/tmp/NestOutput.txt", "size") 225 debug("getStreamEvents", "File size is = [" .. tostring(fileSize) .. "]") 226 227 -- check for new stram events 228 if fileSize then 229 if fileSize > g_fileSize then 230 local file = io.open("/tmp/NestOutput.txt") 231 file:seek("set", g_fileSize) 232 local newEvent = file:read("*a") 233 file:close() 234 newEvent = newEvent:match("data: (.*)}") 235 debug("getStreamEvents", "newEvent = [" .. tostring(newEvent) .. "]") 236 g_fileSize = fileSize 237 if newEvent and newEvent ~= "null" then 238 local response = dkjson.decode(newEvent .. "}") 239 local therm = response.data.thermostats 240 --[[ 241 for key,val in pairs(therm) do 242 for k,v in pairs(val) do 243 debug("getStreamEvents","therm[" .. key .."][" .. tostring(k) .. "]=[" .. tostring(v) .. "]") 244 end 245 end 246 ]] 247 if therm then 248 for i=1,#g_thermostats do 249 if g_thermostats[i].device_id == therm[g_thermostats[i].device_id].device_id then 250 for k,v in pairs(therm[g_thermostats[i].device_id]) do 251 if v ~= g_thermostats[i][k] then 252 g_thermostats[i][k] = v 253 flagThermostat = true 254 debug("getStreamEvents", "updating g_thermostats[" .. i .. "][" .. k .. "] with value =" .. tostring(v)) 255 end 256 end 257 end 258 end 259 end 260 debug("getStreamEvents", "Verifying Smoke and CO detector/s!") 261 local smokePoll = response.data.smoke_co_alarms 262 --[[ 263 for key, val in pairs(smokePoll) do 264 for k,v in pairs(val) do 265 debug("getStreamEvents","smokePoll[" .. key .."][" .. tostring(k) .. "]=[" .. tostring(v) .. "]") 266 end 267 end 268 ]] 269 if smokePoll then 270 for i=1,#g_smoke do 271 if g_smoke[i].device_id == smokePoll[g_smoke[i].device_id].device_id then 272 for k,v in pairs(smokePoll[g_smoke[i].device_id]) do 273 if v ~= g_smoke[i][k] then 274 g_smoke[i][k] = v 275 flagSmoke = true 276 debug("getStreamEvents", "updating g_smoke[" .. i .. "][" .. k .. "] with value =" .. tostring(v)) 277 end 278 end 279 end 280 end 281 end 282 end -- if newEvent 283 if flagThermostat then 284 updateThermostatValues() 285 end 286 if flagSmoke then 287 --updateSmokeValues() 288 end 289 end -- if fileSize > g_fileSize 290 end 291 -- check file size and delete if needed 292 if tonumber(fileSize) > g_maxFileSize then 293 -- delete /tmp/NestOutput.txt file & restart streaming 294 startStreaming() 295 debug("getStreamEvents", "Restarting Streaming!") 296 end 297 luup.call_delay("getStreamEvents", POLLING_RATE) 298 end 299 300 local function getNestData() 301 local url = g_URL .. "?auth=" .. nest_token 302 local header = "-H 'Accept: application/json'" 303 local response, response_string = nestRequest("GET", header, url, "") 304 if not response then 305 debug("getNestData", "ERROR : Could not get Nest Data!") 306 else 307 debug("getNestData", "Nest Data = " .. response_string) 308 if response.devices.thermostats then 309 local count = 1 310 g_thermostats[count] = {} 311 for k,v in pairs(response.devices.thermostats) do 312 g_thermostats[count].device_id = v.device_id 313 g_thermostats[count].name = v.name 314 g_thermostats[count].name_long = v.name_long 315 g_thermostats[count].locale = v.locale 316 g_thermostats[count].structure_id = v.structure_id 317 g_thermostats[count].software_version = v.software_version 318 g_thermostats[count].is_online = v.is_online 319 g_thermostats[count].last_connection = v.last_connection 320 g_thermostats[count].can_cool = v.can_cool 321 g_thermostats[count].can_heat = v.can_heat 322 g_thermostats[count].is_using_emergency_heat = v.is_using_emergency_heat 323 g_thermostats[count].has_fan = v.has_fan 324 g_thermostats[count].fan_timer_active = v.fan_timer_active 325 g_thermostats[count].fan_timer_timeout = v.fan_timer_timeout 326 g_thermostats[count].has_leaf = v.has_leaf 327 g_thermostats[count].temperature_scale = v.temperature_scale 328 g_thermostats[count].target_temperature_f = v.target_temperature_f 329 g_thermostats[count].target_temperature_c = v.target_temperature_c 330 g_thermostats[count].target_temperature_high_f = v.target_temperature_high_f 331 g_thermostats[count].target_temperature_high_c = v.target_temperature_high_c 332 g_thermostats[count].target_temperature_low_f = v.target_temperature_low_f 333 g_thermostats[count].target_temperature_low_c = v.target_temperature_low_c 334 g_thermostats[count].away_temperature_high_f = v.away_temperature_high_f 335 g_thermostats[count].away_temperature_high_c = v.away_temperature_high_c 336 g_thermostats[count].away_temperature_low_f = v.away_temperature_low_f 337 g_thermostats[count].away_temperature_low_c = v.away_temperature_low_c 338 g_thermostats[count].hvac_mode = v.hvac_mode 339 g_thermostats[count].ambient_temperature_f = v.ambient_temperature_f 340 g_thermostats[count].ambient_temperature_c = v.ambient_temperature_c 341 g_thermostats[count].humidity = v.humidity 342 count = count + 1 343 end 344 end 345 if response.devices.smoke_co_alarms then 346 local count = 1 347 g_smoke[count] = {} 348 for k,v in pairs(response.devices.smoke_co_alarms) do 349 g_smoke[count].name = v.name 350 g_smoke[count].name_long = v.name_long 351 g_smoke[count].locale = v.locale 352 g_smoke[count].structure_id = v.structure_id 353 g_smoke[count].software_version = v.software_version 354 g_smoke[count].device_id = v.device_id 355 g_smoke[count].is_online = v.is_online 356 g_smoke[count].last_connection = v.last_connection 357 g_smoke[count].battery_health = v.battery_health 358 g_smoke[count].co_alarm_state = v.co_alarm_state 359 g_smoke[count].smoke_alarm_state = v.smoke_alarm_state 360 g_smoke[count].ui_color_state = v.ui_color_state 361 count = count + 1 362 end 363 end 364 if response.devices.structures then 365 local count = 1 366 g_structures[count] = {} 367 for k,v in pairs(response.structures) do 368 g_structures[count].structure_id = v.structure_id 369 g_structures[count].thermostats = v.thermostats 370 g_structures[count].smoke_co_alarms = v.smoke_co_alarms 371 g_structures[count].name = v.name 372 g_structures[count].away = v.away 373 -- [[ 374 g_structures[count].is_online = v.is_online 375 g_structures[count].last_connection = v.last_connection 376 g_structures[count].battery_health = v.battery_health 377 g_structures[count].co_alarm_state = v.co_alarm_state 378 g_structures[count].smoke_alarm_state = v.smoke_alarm_state 379 g_structures[count].ui_color_state = v.ui_color_state 380 -- ]] 381 count = count + 1 382 end 383 end 384 end 385 end 386 387 local function loginToNest(device, username, password) 388 389 local url = "https://home.nest.com/user/login" 390 local curlCommand = "curl -k --data 'username=" .. g_username .. "&password=" ..g_password .. "' https://home.nest.com/user/login" 391 log("loginToNest", "curlCommand = " .. tostring(curlCommand)) 392 local stdout = io.popen(curlCommand) 393 local response = stdout:read("*a") 394 stdout:close() 395 log("loginToNest", "curlCommand Response = " .. tostring(response)) 396 local json_response = dkjson.decode(response) 397 local data = {} 398 if json_response.error then 399 log("loginToNest", "error = " .. json_response.error) 400 log("loginToNest", "description = " .. json_response.error_description) 401 else 402 data.transport_url = json_response.urls.transport_url 403 data.userid = json_response.userid 404 data.access_token = json_response.access_token 405 end 406 log("loginToNest","data.transport_url = [" .. data.transport_url .. "]" ) 407 log("loginToNest","data.userid = [" .. data.userid .. "]" ) 408 log("loginToNest","data.access_token = [" .. data.access_token .. "]" ) 409 url = "https://developer-api.nest.com/?auth=" .. data.access_token 410 log("loginToNest","URL = [" .. url .. "]" ) 411 curlCommand = "curl -k -L -X GET -H 'Accept: application/json '" .. url 412 log("loginToNest", "curlCommand2 = " .. tostring(curlCommand)) 413 stdout = io.popen(curlCommand) 414 response = stdout:read("*a") 415 stdout:close() 416 log("loginToNest", "curlCommand2 Response = " .. tostring(response)) 417 local json_response = dkjson.decode(response) 418 end 268 419 --------------------------------------------------------- 269 420 ---------------System Command Group---------------------- 270 421 --------------------------------------------------------- 271 422 local function updateThermostatValues() 423 debug("updateThermostatValues","Verifying... ") 424 local CurrentTemperature = 0 425 local CurrentSetpoint = 0 426 local SetpointTarget = 0 427 local ModeStatus = "" 428 local CurrentHumidity = 0 429 for key, value in pairs(g_thermostats) do 430 CurrentTemperature = tostring(value["ambient_temperature_" .. temperatureScale]) 431 CurrentSetpoint = tostring(value["target_temperature_" .. temperatureScale]) 432 ModeStatus = tostring(value.hvac_mode) 433 CurrentHumidity = value.humidity 434 if ModeStatus == "heat" then 435 ModeStatus = "HeatOn" 436 elseif ModeStatus == "cool" then 437 ModeStatus = "CoolOn" 438 elseif ModeStatus == "heat-cool" then 439 ModeStatus = "AutoChangeOver" 440 elseif ModeStatus == "off" then 441 ModeStatus = "Off" 442 end 443 444 local AllSetpoints = CurrentSetpoint .. "," .. CurrentSetpoint .. ",0" 445 --debug("updateThermostatValues","CurrentTemperature = " .. tostring(CurrentTemperature) .. " CurrentSetpoint = " .. tostring(CurrentSetpoint) .. " AllSetpoints = " .. tostring(AllSetpoints)) 446 --debug("updateThermostatValues","DEVICE ID = " .. tostring(value.vera_id)) 447 448 local ModeStatusUI = luup.variable_get("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", tonumber(value.vera_id)) or "" 449 local CurrentSetpointUI = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", tonumber(value.vera_id)) or "" 450 local CurrentTemperatureUI = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", tonumber(value.vera_id)) or "" 451 local HumidityUI = luup.variable_get("urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", tonumber(value.vera_id)) or "" 452 453 if ModeStatus ~= ModeStatusUI then 454 luup.variable_set("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", ModeStatus, tonumber(value.vera_id)) 455 end 456 if CurrentSetpoint ~= CurrentSetpointUI then 457 luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", CurrentSetpoint, tonumber(value.vera_id)) 458 luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "AllSetpoints", AllSetpoints, tonumber(value.vera_id)) 459 end 460 if CurrentTemperature ~= CurrentTemperatureUI then 461 luup.variable_set("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", CurrentTemperature, tonumber(value.vera_id)) 462 end 463 if tonumber(HumidityUI) ~= CurrentHumidity then 464 luup.variable_set("urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", CurrentHumidity ,tonumber(value.humidityDevice_id)) 465 end 466 end 467 end 468 469 local function updateSmokeValues() 470 471 end 272 472 --------------------------------------------------------- 273 473 ---------------Action Implementations-------------------- … … 277 477 luup.task("Clearing...", TASK.SUCCESS, "BoschPlugin", g_taskHandle) 278 478 end 279 debug("(Bosch Plugin)::(clearTask) : Clearing task... ") 280 end 281 282 479 debug("clearTask", "Clearing task... ") 480 end 481 482 function setModeTarget(device, mode) 483 local VeraMode = mode 484 if mode == "HeatOn" then 485 mode = "heat" 486 elseif mode == "CoolOn" then 487 mode = "cool" 488 elseif mode == "AutoChangeOver" then 489 mode = "heat-cool" 490 elseif mode == "Off" then 491 mode = "off" 492 end 493 494 local thermostatID = getNestDeviceID(device, g_thermostats) 495 496 --curl -v -L -X PUT "https://developer-api.nest.com/structures/g-9y-2xkHpBh1MGkVaqXOGJiKOB9MkoW1hhYyQk2vAunCK8a731jbg?auth=<AUTH_TOKEN>" -H "Content-Type: application/json" -d '{"away":"away"}' 497 local url = g_URL .. "/devices/thermostats/" .. tostring(thermostatID) .. "?auth=" .. nest_token 498 local header = "-H 'Content-Type: application/json'" 499 local data = "-d '{\"hvac_mode\" : \"" .. mode .."\" }'" 500 log("setModeTarget", "data = " .. data) 501 local response, response_string = nestRequest("PUT", header, url, data) 502 if not response then 503 log("setModeTarget", "ERROR : Could not set Data!") 504 else 505 log("setModeTarget", "Nest Response = " .. response_string) 506 luup.variable_set("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", VeraMode, device) 507 end 508 end 509 510 function setCurrentSetpoint(device, value) 511 local thermostatID = getNestDeviceID(device, g_thermostats) 512 513 if tonumber(value) > 32 then 514 value = "32" 515 end 516 --curl -v -L -X PUT "https://developer-api.nest.com/structures/g-9y-2xkHpBh1MGkVaqXOGJiKOB9MkoW1hhYyQk2vAunCK8a731jbg?auth=<AUTH_TOKEN>" -H "Content-Type: application/json" -d '{"away":"away"}' 517 local url = g_URL .. "/devices/thermostats/" .. tostring(thermostatID) .. "?auth=" .. nest_token 518 local header = "-H 'Content-Type: application/json'" 519 local data = "-d '{\"target_temperature_" .. temperatureScale .. "\" :" .. tonumber(value) .. "}'" 520 log("setCurrentSetpoint", "data = " .. data) 521 local response, response_string = nestRequest("PUT", header, url, data) 522 if not response then 523 log("setCurrentSetpoint", "ERROR : Could not set Data!") 524 else 525 log("setCurrentSetpoint", "Request OK, Response = " .. response_string) 526 local all = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1", "AllSetpoints", device) or "" 527 local now = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", device) or "" 528 all = string.gsub( all, now, value, 1 ) 529 log("setCurrentSetpoint", "ALL = [" .. all .. "]") 530 luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "AllSetpoints", all, device) 531 luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", value, device) 532 end 533 end 534 535 function setArmed(device, value) 536 luup.variable_set(SID.SES, "Armed", value, device) 537 end 538 539 function setTarget(device, value) 540 luup.variable_set(SID.SWP, "Status", value, device) 541 luup.variable_set(SID.SWP, "Target", value, device) 542 end 543 544 function connectWithNest(device, username, password) 545 log("connectWithNest", "AM AJUNS!!!!") 546 loginToNest(device, username, password) 547 end 283 548 --------------------------------------------------------- 284 549 ---------------Initialization Functions------------------ … … 287 552 for dev, attr in pairs(luup.devices) do 288 553 if (attr.device_num_parent == device) then 289 local zoneNo = attr.id:match("^bosch_point_(%d+)") 290 local partitionNo = attr.id:match("^bosch_area_(%d+)") 291 local outputNo = attr.id:match("^bosch_output_(%d+)_") 292 for k,v in pairs(g_areas) do 293 if partitionNo == tostring(v.panelID) then 294 partitionNo = tostring(k) 295 end 296 end 297 if (zoneNo ~= nil) then 298 zoneNo = tonumber(zoneNo, 10) 299 g_points[zoneNo].devId = dev 300 elseif (partitionNo ~= nil) then 301 partitionNo = tonumber(partitionNo, 10) 302 g_areas[partitionNo].devId = dev 303 else 304 if (outputNo ~= nil) then 305 outputNo = tonumber(outputNo, 10) 306 for key,val in pairs(g_outputs) do 307 if outputNo == tonumber(val.panelID) then 308 g_outputs[key].devId = dev 309 end 554 local thermostatID = attr.id:match("^nest_thermostat_(.+)") 555 local smokeID = attr.id:match("^nest_sco_(.+)") 556 local humidity = attr.id:match("^nest_humidity_(.+)") 557 if thermostatID then 558 for k,v in pairs(g_thermostats) do 559 if thermostatID == tostring(v.device_id) then 560 g_thermostats[tonumber(k)].vera_id = dev 310 561 end 311 562 end 312 563 end 313 end 314 end 315 end 316 317 local function appendPoints() 318 local count = 0 319 for i, v in ipairs(g_points) do 320 debug("(Bosch Plugin)::(appendPoints) : Appending zone ".. i ..".") 321 local device = getDeviceType(i) 322 luup.chdev.append(lug_device, g_appendPtr, "bosch_point_"..i, "Point ".. i ..": ".. v.label, device.type, device.file, nil, nil, false) 323 if count > 20 then 324 debug("(Bosch Plugin)::(appendPoints) : Possible error in generating points, more then 20 devices were generated!!!") 325 FLAGS.ZONES = true 326 return 327 end 328 end 329 FLAGS.ZONES = true 330 end 331 332 local function appendAreas() 333 local count = 0 334 for i, v in ipairs(g_areas) do 335 debug("(Bosch Plugin)::(appendAreas) : Appending partition ".. i ..".") 336 luup.chdev.append(lug_device, g_appendPtr, "bosch_area_".. v.panelID, "Area Control ".. v.panelID ..": ".. v.name, "urn:schemas-micasaverde-com:device:BoschAlarmPartition:1", "D_BoschAlarmPartition1.xml", nil, nil, false) 564 if smokeID then 565 for k,v in pairs(g_smoke) do 566 if smokeID == tostring(v.device_id) then 567 g_smoke[tonumber(k)].vera_id = dev 568 end 569 end 570 end 571 if humidity then 572 for k,v in pairs(g_thermostats) do 573 if humidity == tostring(v.device_id) then 574 g_thermostats[tonumber(k)].humidityDevice_id = dev 575 end 576 end 577 end 578 end 579 end 580 end 581 582 583 local function appendDevices() 584 local count = 0 585 for k, v in ipairs(g_thermostats) do 586 debug("appendDevices", "Appending thermostat ".. v.name ..".") 587 luup.chdev.append(lug_device, g_appendPtr, "nest_thermostat_".. v.device_id, v.name, DEVICE_TYPES.THERMOSTAT, DEVICE_FILES.THERMOSTAT, nil, nil, false) 588 debug("appendDevices", "Appending Home/Away ".. v.name ..".") 589 luup.chdev.append(lug_device, g_appendPtr, "nest_home_away_".. v.device_id, v.name, DEVICE_TYPES.BINARY_LIGHT, DEVICE_FILES.BINARY_LIGHT, nil, nil, false) 590 if v.humidity then 591 debug("appendDevices", "Appending humidity ".. v.name ..".") 592 luup.chdev.append(lug_device, g_appendPtr, "nest_humidity_".. v.device_id, "Humidity - " ..v.name, DEVICE_TYPES.HUMIDITY, DEVICE_FILES.HUMIDITY, nil, "urn:micasaverde-com:serviceId:HumiditySensor1,CurrentLevel=" .. v.humidity, false) 593 end 337 594 count = count + 1 338 595 if count > 20 then 339 debug("(Bosch Plugin)::(appendAreas) : Possible error in generating areas, more then 20 devices were generated!!!") 340 FLAGS.PARTITIONS = true 596 debug("appendDevices", "Possible error in generating outputs, more then 20 devices were generated!!!") 341 597 return 342 598 end 343 599 end 344 FLAGS.PARTITIONS = true 345 end 346 347 local function appendOutputs() 348 local count = 0 349 for i, v in ipairs(g_outputs) do 350 debug("(Bosch Plugin)::(appendOutputs) : Appending output ".. v.name ..".") 351 luup.chdev.append(lug_device, g_appendPtr, "bosch_output_".. v.panelID .. "_" .. v.name, v.name, DEVICE_TYPES.BINARY_LIGHT, DEVICE_FILES.BINARY_LIGHT, nil, nil, false) 600 601 for k, v in ipairs(g_smoke) do 602 debug("appendDevices", "Appending smoke sensor ".. v.name ..".") 603 luup.chdev.append(lug_device, g_appendPtr, "nest_sco_".. v.device_id, v.name, DEVICE_TYPES.SMOKE_SENSOR, DEVICE_FILES.SMOKE_SENSOR, nil, nil, false) 352 604 count = count + 1 353 605 if count > 20 then 354 debug(" (Bosch Plugin)::(appendOutputs) :Possible error in generating outputs, more then 20 devices were generated!!!")606 debug("appendDevices", "Possible error in generating outputs, more then 20 devices were generated!!!") 355 607 return 356 608 end … … 359 611 360 612 local function getInfos(device) 361 local debugMode = luup.variable_get(SID.BOSCH, "DebugMode", device) or "" 613 614 local flagError = false 615 616 local debugMode = luup.variable_get(SID.NEST, "DebugMode", device) or "" 362 617 if (debugMode ~= "") then 363 618 DEBUG_MODE = (debugMode == "1") and true or false 364 619 else 365 luup.variable_set(SID. BOSCH, "DebugMode", (DEBUG_MODE and "1" or "0"), device)366 end 367 log(" (Bosch Plugin)::(getDebugMode) :Debug mode "..(DEBUG_MODE and "enabled" or "disabled")..".")368 369 local polling_rate = luup.variable_get(SID. BOSCH, "POLLING_RATE", device) or ""620 luup.variable_set(SID.NEST, "DebugMode", (DEBUG_MODE and "1" or "0"), device) 621 end 622 log("getInfos", "Debug mode "..(DEBUG_MODE and "enabled" or "disabled")..".") 623 624 local polling_rate = luup.variable_get(SID.NEST, "POLLING_RATE", device) or "" 370 625 if (polling_rate ~= "") then 371 626 POLLING_RATE = tonumber(polling_rate) 372 627 else 373 luup.variable_set(SID.BOSCH, "POLLING_RATE", POLLING_RATE, device) 374 end 375 debug("(Bosch Plugin)::(getDebugMode) : POLLING_RATE = " .. POLLING_RATE ) 376 377 local safestorage = luup.variable_get(SID.BOSCH,"SafeStorage",lug_device) or "" 378 if safestorage == "" then 379 luup.variable_set(SID.BOSCH,"SafeStorage","0",lug_device) 380 end 381 382 local passcode = luup.variable_get(SID.BOSCH,"Passcode",lug_device) or "" 383 if passcode == "" then 384 luup.variable_set(SID.BOSCH,"Passcode","Bosch_Auto",lug_device) 385 end 386 387 local trash 388 ipAddress, trash, ipPort = string.match(luup.devices[device].ip, "^([%w%.%-]+)(:?(%d-))$") 389 if ipAddress and ipAddress ~= "" then 390 if ipPort==nil or ipPort == "" then 391 ipPort = "7700" 392 end 393 return true 394 else 395 log("(Bosch Plugin)::(getDebugMode) : ERROR : Insert IP address!") 396 return false 397 end 398 end 399 400 401 local function connectToPanel() 402 local retry 403 local i 404 local flagConnect = false 405 local flagPass = false 406 local passcode 407 408 local safestorage = luup.variable_get(SID.BOSCH,"SafeStorage",lug_device) or "" 409 if safestorage == "" then 410 luup.variable_set(SID.BOSCH,"SafeStorage","0",lug_device) 411 safestorage = "0" 412 end 413 414 if safestorage == "0" then 415 passcode = luup.variable_get(SID.BOSCH,"Passcode",lug_device) or "" 416 if passcode == "" then 417 luup.variable_set(SID.BOSCH,"Passcode","Bosch_Auto",lug_device) 418 log("(Bosch Plugin)::(connectToPanel) : ERROR : Password field have a default value!") 419 displayMessage("Password field have a default value!", TASK.ERROR) 628 luup.variable_set(SID.NEST, "POLLING_RATE", POLLING_RATE, device) 629 end 630 debug("getInfos", "POLLING_RATE = " .. POLLING_RATE ) 631 632 local username = luup.devices[device].user or "" 633 local password = luup.devices[device].pass or "" 634 635 getTemperatureScale() 636 log("getInfos", "Temperature Scale is = " .. temperatureScale) 637 638 if username == "" then 639 luup.attr_set("username","default",device) 640 g_username = "default" 641 flagError = true 642 else 643 if username == "default" then 644 flagError = true 645 else 646 g_username = username 647 end 648 end 649 650 if password == "" then 651 luup.attr_set("password","default",device) 652 g_password = "default" 653 flagError = true 654 else 655 if password == "default" then 656 flagError = true 420 657 else 421 g_passcode = passcode 422 flagPass = true 423 end 424 elseif safestorage == "1" then 425 local file = io.open("/tmp/credential.txt") 426 if file then 427 for line in file:lines() do 428 passcode = line:match('^(.-)$') 429 end 430 file:close() 431 if passcode then 432 g_passcode = passcode 433 flagPass = true 434 else 435 log("(Bosch Plugin)::(connectToPanel) : ERROR : Please insert your passcode in file!") 436 displayMessage("Please insert your passcode in file!", TASK.ERROR) 437 end 438 else 439 log("(Bosch Plugin)::(connectToPanel) : ERROR : Couldn't open passcode file!") 440 displayMessage("Couldn't open passcode file!", TASK.ERROR) 441 end 442 else 443 log("(Bosch Plugin)::(connectToPanel) : ERROR : Invalid SafeStorage value. Please insert a valid one(0 or 1)!") 444 displayMessage("Invalid SafeStorage value. Please insert a valid one(0 or 1)!", TASK.ERROR) 445 end 446 447 if flagPass then 448 for i = 1, 10 do 449 retry = peer:connect(ipAddress, ipPort) 450 if retry then 451 flagConnect = true 452 break 453 else 454 debug("(Bosch Plugin)::(connectToPanel) : ERROR : Cannot connect to panel!") 455 end 456 end 457 if flagConnect then 458 peer = assert( ssl.wrap(peer, params) ) 459 peer:settimeout(0.3) 460 461 local succ, err = peer:dohandshake() 462 while not succ do 463 wait(peer, err) 464 succ, err = peer:dohandshake() 465 end 466 debug("*** Handshake done ***") 467 local responseArray = {} 468 local responseString 469 responseString = WhatAreYou() 470 if responseString then 471 responseArray = parse(responseString,{}) 472 else 473 debug("(Bosch Plugin)::(connectToPanel) : ERROR : Handshake ERROR!") 474 end 475 responseString = PasscodeAndUserTypeCheck(g_passcode) 476 if responseString then 477 responseArray = parse(responseString,{}) 478 if responseArray[3] == "FE" then 479 if responseArray[4] == "00" then 480 log("(Bosch Plugin)::(connectToPanel) : ERROR : Passcode and User Type Check ERROR! Another Session is opened, cannot authentify !") 481 flagPasscode = false 482 elseif responseArray[4] == "01" then 483 log("(Bosch Plugin)::(connectToPanel) : OK : Passcode and User Type Check OK! continuing ...") 484 flagPasscode = true 485 else 486 log("(Bosch Plugin)::(connectToPanel) : ERROR : Unknown Passcode and User Type Check ERROR! FE : [" .. responseArray[4] .. "]") 487 flagPasscode = false 488 end 489 elseif responseArray[3] == "FD" then 490 log("(Bosch Plugin)::(connectToPanel) : ERROR : NAK received with error code " .. responseArray[4]) 491 flagPasscode = false 492 elseif responseArray[3] == "FC" then 493 log("(Bosch Plugin)::(connectToPanel) : ERROR : ACK received") 494 flagPasscode = false 495 else 496 log("(Bosch Plugin)::(connectToPanel) : ERROR : Unknown ERROR (we should not be here)") 497 flagPasscode = false 498 end 499 else 500 log("(Bosch Plugin)::(connectToPanel) ERROR : PasscodeAndUserTypeCheck error!") 501 end 502 else 503 log("(Bosch Plugin)::(connectToPanel) : ERROR : Please check IP and PORT settings!") 504 displayMessage("Please check IP and PORT settings!", TASK.ERROR_STOP) 505 end 506 else 507 log("(Bosch Plugin)::(connectToPanel) : ERROR : Please check Passcode settings!") 508 displayMessage("Please check Passcode settings!", TASK.ERROR) 509 end 510 end 511 658 g_password = password 659 end 660 end 661 662 local token = luup.variable_get(SID.NEST, "TOKEN", device) or "" 663 if token ~= "" and token ~= "default" then 664 nest_token = token 665 else 666 luup.variable_set(SID.NEST, "TOKEN", "default", device) 667 end 668 return flagError 669 end 512 670 513 671 function Init(lul_device) 514 515 672 lug_device = lul_device 516 673 g_taskHandle = luup.task("Starting up...", TASK.BUSY, "Vera Connect WWN", g_taskHandle) 674 local continue = getInfos(lug_device) 675 if continue then 676 return false, "Username and/or password not set. Please add them in 'Advance' tab!", "Vera Connect WWN" 677 end 678 getNestData() 679 g_appendPtr = luup.chdev.start(lug_device) 680 appendDevices(lug_device) 681 luup.chdev.sync(lug_device, g_appendPtr) 682 getChildDevices(lug_device) 683 log("Init", "Updating thermostat values!") 684 updateThermostatValues() 685 log("Init", "Trying to start streaming and get the latest event/s!") 686 startStreaming() 687 getStreamEvents() 688 ------------------------------- 689 for i=1,#g_thermostats do 690 for k,v in pairs(g_thermostats[i]) do 691 log("Init","g_thermostats[".. i .."].[" .. tostring(k) .. "]=[" .. tostring(v) .. "]") 692 end 693 end 694 for i=1,#g_smoke do 695 for k,v in pairs(g_smoke[i]) do 696 log("Init","g_smoke[".. i .."].[" .. tostring(k) .. "]=[" .. tostring(v) .. "]") 697 end 698 end 699 for i=1,#g_structures do 700 for k,v in pairs(g_structures[i]) do 701 log("Init","g_structures[".. i .."].[" .. tostring(k) .. "]=[" .. tostring(v) .. "]") 702 end 703 end 704 ------------------------------ 517 705 log( "Startup", "Startup Successful" ) 518 706 g_taskHandle = luup.task("Startup successful.", TASK.BUSY, "Vera Connect WWN", g_taskHandle) 519 707 luup.set_failure(0, lul_device) 520 708 return true, "Startup successful.", "Vera Connect WWN" 521 522 end 709 end -
/trunk/D_VeraConnectWWN1.json
r1 r3 15 15 "Position": "0", 16 16 "TabType": "flash", 17 "top_navigation_tab" : 1, 17 18 "SceneGroup":[ 18 19 { … … 35 36 "ControlType": "label", 36 37 "Label": { 37 "lang_tag": " list_zones",38 "text": " Points:"38 "lang_tag": "username_label", 39 "text": "Userame : " 39 40 }, 40 41 "Display": { 41 42 "Top": 20, 42 "Left": 70,43 "Left": 40, 43 44 "Width": 75, 44 45 "Height": 20 … … 47 48 { 48 49 "ControlType": "input", 49 "ID": " ListVal",50 "ID": "username", 50 51 "Display": { 51 "Top": 40, 52 "Left": 70, 52 "Top": 20, 53 "Left": 130, 54 "Width":100, 55 "Height": 20 56 } 57 }, 58 { 59 "ControlType": "label", 60 "Label": { 61 "lang_tag": "password_label", 62 "text": "Password : " 63 }, 64 "Display": { 65 "Top": 50, 66 "Left": 40, 53 67 "Width": 75, 68 "Height": 20 69 } 70 }, 71 { 72 "ControlType": "input", 73 "ID": "password", 74 "Display": { 75 "Top": 50, 76 "Left": 130, 77 "Width": 100, 54 78 "Height": 20 55 79 } … … 58 82 "ControlType": "button", 59 83 "Label": { 60 "lang_tag": "button_ bypass",61 "text": " Bypass"84 "lang_tag": "button_connect", 85 "text": "Connect with Nest" 62 86 }, 63 87 "Display": { 64 "Top": 70,65 "Left": 70,88 "Top": 80, 89 "Left": 40, 66 90 "Width": 60, 67 91 "Height": 20 … … 69 93 "Command": { 70 94 "Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1", 71 "Action": " SendBypassPoints",95 "Action": "ConnectWithNest", 72 96 "Parameters": [ 73 97 { 74 "Name": "List", 75 "ID": "ListVal" 76 } 77 ] 78 } 79 }, 80 { 81 "ControlType": "button", 82 "Label": { 83 "lang_tag": "button_activate", 84 "text": "Unbypass" 85 }, 86 "Display": { 87 "Top": 95, 88 "Left": 70, 89 "Width": 60, 90 "Height": 20 91 }, 92 "Command": { 93 "Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1", 94 "Action": "SendUnbypassPoints", 95 "Parameters": [ 98 "Name": "Username", 99 "ID": "username" 100 }, 96 101 { 97 "Name": " List",98 "ID": " ListVal"102 "Name": "Password", 103 "ID": "password" 99 104 } 100 105 ] … … 104 109 }, 105 110 { 106 "Label": { 107 "lang_tag": "history", 108 "text": "History" 109 }, 110 "Position": "0", 111 "TabType": "flash", 112 "SceneGroup":[ 113 { 114 "id": "1", 115 "top": "1", 116 "left": "0", 117 "x": "1", 118 "y": "1" 119 } 120 ], 121 "ControlGroup": [ 122 { 123 "id": "1", 124 "isSingle": "0", 125 "scenegroup": "1" 126 } 127 ], 128 "Control": [ 129 { 130 "ControlType": "label", 131 "Label": { 132 "lang_tag": "History_event_interval : ", 133 "text": "History event interval:" 134 }, 135 "Display": { 136 "Top": 20, 137 "Left": 200, 138 "Width": 100, 139 "Height": 20 140 } 141 }, 142 { 143 "ControlType": "variable", 144 "Display": { 145 "Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1", 146 "Variable": "Interval", 147 "Top": 20, 148 "Left": 340, 149 "Width": 75, 150 "Height": 20 151 } 152 }, 153 { 154 "ControlType": "label", 155 "Label": { 156 "lang_tag": "start_event : ", 157 "text": "Start event number:" 158 }, 159 "Display": { 160 "Top": 45, 161 "Left": 200, 162 "Width": 75, 163 "Height": 20 164 } 165 }, 166 { 167 "ControlType": "input", 168 "ID": "startEventNo", 169 "Display": { 170 "Top": 70, 171 "Left": 200, 172 "Width": 75, 173 "Height": 20 174 } 175 }, 176 { 177 "ControlType": "label", 178 "Label": { 179 "lang_tag": "number_of_events : ", 180 "text": "Number of events:" 181 }, 182 "Display": { 183 "Top": 45, 184 "Left": 330, 185 "Width": 75, 186 "Height": 20 187 } 188 }, 189 { 190 "ControlType": "input", 191 "ID": "numberOfEvents", 192 "Display": { 193 "Top": 70, 194 "Left": 330, 195 "Width": 75, 196 "Height": 20 197 } 198 }, 199 { 200 "ControlType": "button", 201 "Label": { 202 "lang_tag": "get_history", 203 "text": "Get History" 204 }, 205 "Display": { 206 "Top": 100, 207 "Left": 265, 208 "Width": 80, 209 "Height": 20 210 }, 211 "Command": { 212 "Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1", 213 "Action": "GetHistory", 214 "Parameters": [ 215 { 216 "Name": "EventNo", 217 "ID": "numberOfEvents" 218 }, 219 { 220 "Name": "StartEvent", 221 "ID": "startEventNo" 222 } 223 ] 224 } 225 }, 226 { 227 "ControlType": "variable", 228 "left": "1", 229 "Display": { 230 "Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1", 231 "Variable": "HistoryLog", 232 "Top": 140, 233 "Left": 200, 234 "Width": 200, 235 "Height": 200 236 } 237 } 238 ] 111 "Label": { 112 "lang_tag": "authorize", 113 "text": "Authorize" 114 }, 115 "Position": "1", 116 "TopNavigationTab": "1", 117 "TabType": "javascript", 118 "ScriptName": "J_VeraConnectWWN1.js", 119 "Function": "VeraConnectWWN.init" 239 120 }, 240 121 { … … 243 124 "text": "Advanced" 244 125 }, 245 "Position": " 1",126 "Position": "2", 246 127 "TabType": "javascript", 247 128 "ScriptName": "shared.js", -
/trunk/S_VeraConnectWWN1.xml
r1 r3 29 29 <actionList> 30 30 <action> 31 <name> StorePinCode</name>31 <name>ConnectWithNest</name> 32 32 <argumentList> 33 33 <argument> 34 <name> PinCode</name>34 <name>Username</name> 35 35 <direction>in</direction> 36 <relatedStateVariable>ui4</relatedStateVariable> 36 <relatedStateVariable>string</relatedStateVariable> 37 </argument> 38 <argument> 39 <name>Password</name> 40 <direction>in</direction> 41 <relatedStateVariable>string</relatedStateVariable> 37 42 </argument> 38 43 </argumentList> 39 44 </action> 40 <action>41 <name>ClearPinCode</name>42 <argumentList></argumentList>43 </action>44 <action>45 <name>ClearTask</name>46 <argumentList></argumentList>47 </action>48 45 </actionList> 49 46 </scpd> -
/trunk/D_VeraConnectWWN1.xml
r1 r3 18 18 <SCPDURL>S_VeraConnectWWN1.xml</SCPDURL> 19 19 </service> 20 <service> 21 <Optional/> 22 <serviceType>urn:schemas-upnp-org:service:HVAC_FanOperatingMode:1</serviceType> 23 <serviceId>urn:upnp-org:serviceId:HVAC_FanOperatingMode1</serviceId> 24 <SCPDURL>S_HVAC_FanOperatingMode1.xml</SCPDURL> 25 </service> 26 <service> 27 <serviceType>urn:micasaverde-com:serviceId:HVAC_OperatingState:1</serviceType> 28 <serviceId>urn:micasaverde-com:serviceId:HVAC_OperatingState1</serviceId> 29 <SCPDURL>S_HVAC_OperatingState1.xml</SCPDURL> 30 </service> 31 <service> 32 <serviceType>urn:schemas-upnp-org:service:HVAC_UserOperatingMode:1</serviceType> 33 <serviceId>urn:upnp-org:serviceId:HVAC_UserOperatingMode1</serviceId> 34 <SCPDURL>S_HVAC_UserOperatingMode1.xml</SCPDURL> 35 </service> 36 <service> 37 <Optional/> 38 <serviceType>urn:schemas-upnp-org:service:FanSpeed:1</serviceType> 39 <serviceId>urn:upnp-org:serviceId:FanSpeed1</serviceId> 40 <SCPDURL>S_FanSpeed1.xml</SCPDURL> 41 </service> 42 <service> 43 <serviceType>urn:schemas-upnp-org:service:TemperatureSensor:1</serviceType> 44 <serviceId>urn:upnp-org:serviceId:TemperatureSensor1</serviceId> 45 <SCPDURL>S_TemperatureSensor1.xml</SCPDURL> 46 </service> 47 <service> 48 <serviceType>urn:schemas-upnp-org:service:TemperatureSetpoint:1</serviceType> 49 <serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1</serviceId> 50 <SCPDURL>S_TemperatureSetpoint1.xml</SCPDURL> 51 </service> 52 <service> 53 <serviceType>urn:schemas-upnp-org:service:TemperatureSetpoint:1</serviceType> 54 <serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1_Heat</serviceId> 55 <SCPDURL>S_TemperatureSetpoint1.xml</SCPDURL> 56 </service> 57 <service> 58 <serviceType>urn:schemas-upnp-org:service:TemperatureSetpoint:1</serviceType> 59 <serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1_Cool</serviceId> 60 <SCPDURL>S_TemperatureSetpoint1.xml</SCPDURL> 61 </service> 62 <service> 63 <serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType> 64 <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId> 65 <SCPDURL>S_SwitchPower1.xml</SCPDURL> 66 </service> 67 <service> 68 <serviceType>urn:schemas-micasaverde-com:service:EnergyMetering:1</serviceType> 69 <serviceId>urn:micasaverde-com:serviceId:EnergyMetering1</serviceId> 70 <SCPDURL>S_EnergyMetering1.xml</SCPDURL> 71 </service> 72 <service> 73 <serviceType>urn:schemas-micasaverde-com:service:HaDevice:1</serviceType> 74 <serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId> 75 <SCPDURL>S_HaDevice1.xml</SCPDURL> 76 </service> 20 77 </serviceList> 21 78 <implementationList> -
/trunk/I_VeraConnectWWN1.xml
r1 r3 4 4 local fc = 0 -- failure counter 5 5 function VeraConnectWWNStartup (lul_device) 6 luup.log( "(Vera Connect WWN)::(Startup) : Initiating " )6 luup.log( "(Vera Connect WWN)::(Startup) : Initiating..." ) 7 7 package.loaded.L_Bosch1 = nil 8 8 nestPlugin = require( "L_VeraConnectWWN1" ) … … 11 11 updateState = nestPlugin.updateState 12 12 setTarget = nestPlugin.setTarget 13 --reconnect = boschPlugin.reconnect 13 connectWithNest = nestPlugin.connectWithNest 14 pollNest = nestPlugin.pollNest 15 setModeTarget = nestPlugin.setModeTarget 16 setCurrentSetpoint = nestPlugin.setCurrentSetpoint 17 setMode = nestPlugin.setMode 18 setArmed = nestPlugin.setArmed 19 getStreamEvents = nestPlugin.getStreamEvents 14 20 15 21 return nestPlugin.Init( lul_device ) … … 29 35 <name>SetTarget</name> 30 36 <job> 31 setTarget( lul_settings.newTargetValue, lul_device)37 setTarget(lul_device, lul_settings.newTargetValue) 32 38 </job> 33 39 </action> … … 39 45 </job> 40 46 </action> 47 <action> 48 <serviceId>urn:micasaverde-com:serviceId:VeraConnectWWN1</serviceId> 49 <name>ConnectWithNest</name> 50 <job> 51 connectWithNest (lul_device, lul_settings.username, lul_settings.password) 52 </job> 53 </action> 54 <action> 55 <serviceId>urn:upnp-org:serviceId:HVAC_UserOperatingMode1</serviceId> 56 <name>SetModeTarget</name> 57 <job> 58 setModeTarget (lul_device, lul_settings.NewModeTarget) 59 </job> 60 </action> 61 <action> 62 <serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1</serviceId> 63 <name>SetCurrentSetpoint</name> 64 <job> 65 setCurrentSetpoint (lul_device, lul_settings.NewCurrentSetpoint) 66 </job> 67 </action> 68 <action> 69 <serviceId>urn:upnp-org:serviceId:HVAC_FanOperatingMode1</serviceId> 70 <name>SetMode</name> 71 <job> 72 setMode (lul_device, lul_settings.NewMode) 73 </job> 74 </action> 41 75 </actionList> 42 76 </implementation>
Note: See TracChangeset
for help on using the changeset viewer.