Index: /trunk/L_VeraConnectWWN1.lua
===================================================================
--- /trunk/L_VeraConnectWWN1.lua	(revision 1)
+++ /trunk/L_VeraConnectWWN1.lua	(revision 3)
@@ -1,20 +1,16 @@
 module("L_VeraConnectWWN1", package.seeall)
-
-require("socket")
-local ssl = require("ssl")
-local peer = socket.tcp()
-local params = {
-    mode = "client",
-	protocol = "tlsv1",
-    verify = {"none"},
-	options = {"no_compression"},
-	ciphers = "ALL",
-}
-
+-- andrei : {"access_token":"c.CzL215BijVuzFgznRCW9QKvA0eblyxSMI9ad7klSX87vkpDyI0XxiftueUPWqDim9ejCCrYJ9r0WCHhJz16clWAxoLTqhcbXeYT45kzbeJ8gC5UwLIxdrc0v2teyuVhnSz6ZLmTJ2TEqEXIm","expires_in":315360000}
+-- florin : {"access_token":"c.7zKZ8yzOgDWUKGUTeBKz1JOPRAM6uWOse7Eb6jnfcKTT23hyOLKV5pv3vafKRp6wHlRHkVjknRABDa4NKnxAJNl6lq4GIoJPXIX4mby3ubcMprxqrM2GFN0EGb2WdWQwtsTblXLVgkKvGG2Y","expires_in":315360000}
+
+--require("socket")
+local ltn12 = require("ltn12")
+local dkjson = require ("dkjson")
+local https = require("ssl.https")
+local http = require ("socket.http")
+--local mime = require("mime")
 -- Flags
 local DEBUG_MODE = false
 local FLAGS = {
-	PARTITIONS = false,
-	ZONES = true
+	
 }
 
@@ -23,5 +19,7 @@
 	TEMPERATURE_SENSOR 	= "D_TemperatureSensor1.xml",
 	THERMOSTAT			= "D_HVAC_ZoneThermostat1.xml",
-	SMOKE_SENSOR		= "D_SmokeSensor1.xml"
+	HUMIDITY			= "D_HumiditySensor1.xml",
+	SMOKE_SENSOR		= "D_SmokeSensor1.xml",
+	BINARY_LIGHT		= "D_BinaryLight1.xml"
 }
 
@@ -29,5 +27,7 @@
 	TEMPERATURE_SENSOR 	= "urn:schemas-micasaverde-com:device:TemperatureSensor:1",
 	THERMOSTAT			= "urn:schemas-upnp-org:device:HVAC_ZoneThermostat:1",
-	SMOKE_SENSOR		= "urn:schemas-micasaverde-com:device:SmokeSensor:1"
+	HUMIDITY			= "urn:schemas-micasaverde-com:device:HumiditySensor:1",
+	SMOKE_SENSOR		= "urn:schemas-micasaverde-com:device:SmokeSensor:1",
+	BINARY_LIGHT		= "urn:schemas-upnp-org:device:BinaryLight:1"
 }
 
@@ -55,5 +55,5 @@
 -- LastUpdate
 local DISPLAY_SECONDS = 20
-local POLLING_RATE = 10 -- 5 -- 30 --"PollFrequency"
+local POLLING_RATE = 5 -- 30 --"PollFrequency"
 
 -- Globals
@@ -61,18 +61,31 @@
 local lug_device = nil
 local g_appendPtr -- The pointer passed to luup.chdev.append
-local g_pinCodes = {}
 local g_taskHandle = -1
-local g_errorMessage = nil
 local g_lastTask = os.time() -- The time when the status message was last updated.
-local g_users = nil
-local g_areas = {
+local g_username = ""
+local g_password = ""
+local g_fileSize = 0
+local g_maxFileSize = 5 * 1024 * 1024
+local g_thermostats = {
 	-- .panelID = ""
 	-- .name = ""
 	-- .devId
 }
+local g_smoke = {
+
+}
+local g_structures = {
+
+}
 
 local ipAddress
 local ipPort
-
+local NEST_UA = "Nest/1.1.0.10 CFNetwork/548.0.4"
+local nest_token = ""
+local nest_ClientID = "5b1585a5-b64e-4759-903e-895ac9373245"
+local nest_Secret = "noR9PTaBOHx6kONdieaClyyBX"
+local g_URL = "https://developer-api.nest.com"
+local temperatureScale = ""
+-- 7W69Q34L
 ---------------------------------------------------------
 -----------------Generic Utils---------------------------
@@ -100,161 +113,4 @@
 	g_lastTask = os.time()
 	luup.call_delay("clearTask", DISPLAY_SECONDS)
-end
-
-
-local function wait(peer, err)
-   if err == "timeout" or err == "wantread" then
-		--log("***WANTREAD***")
-		socket.select({peer}, nil,0)
-    elseif err == "wantwrite" then
-		--log("***WANTWRITE***")
-		socket.select(nil, {peer},0)
-    else
-		--peer:close()
-		--os.exit(1)
-    end
-end
-
-local function send(str, peer)
-	local match = {"0","1","2","3","4","5","6","7","8","9"}
-	local length  = tostring(str:len())
-	local tosend = fromhex("01")
-
-	for _,v in pairs(match) do
-		if v == length then
-			length = string.format('%02s',length)
-		end
-	end
-
-	tosend = tosend .. fromhex(length) .. str
-	debug("(Bosch Plugin)::(send) : Sending...")
-	peer:settimeout(0.3)
-	local succ, err = peer:send(tosend)
-	debug("(Bosch Plugin)::(send) : Waiting...")
-	wait(peer, err)
-	if succ then
-		debug("(Bosch Plugin)::(send) : Succesifully sent : [".. tohex(tosend) .. "] with length = [" .. succ .. "]")
-	else
-		debug("(Bosch Plugin)::(send) : Sending error!!! .. Reconnecting ... ")
-		reconnect()
-		if err then
-			debug("(Bosch Plugin)::(send) : ERROR : " .. err)
-		end
-	end
-end
-
-local function receive()
-	local data = nil
-	local status
-	local partials = nil
-	local length = 0
-	local start = os.time()
-	local stop
-	while (not partials) or (tostring(partials)  == "")  do
-		data , status, partials = peer:receive()
-		stop = os.time()
-		if (stop - start) > 10 then
-			debug("partial = [" .. tostring(partial) .. "]")
-			debug("status = [" .. tostring(status) .. "]")
-			debug("data = [" .. tostring(data) .. "]")
-			return
-		end
-	end
-
-	return partials
-end
-
-local function login()
-	-- debug("in login()")
-
-	local data = readSettings()
-
-	-- if there is no username or password, then no matter what, don't proceed
-	if (data.username == "" or data.password == "") then
-		task("Please specify username and password.")
-		clearSession()
-		return
-	end
-
-	-- if there is old session data, it might still be good, so try it!
-	if (data.transport_url ~= "" and data.userid ~= "" and data.access_token ~= "") then
-		debug("assuming saved login credentials are still valid.")
-		return data
-	end
-
-	-- perform https POST to nest.com to login
-	local res = {}
-	local body = urlcode.encodetable{username = data.username, password = data.password}
-	local headers = {["user-agent"] = NEST_UA,
-				   ["content-length"] = string.len(body),
-				   ["content-type"] = "application/x-www-form-urlencoded"}
-	local url = { url = "https://home.nest.com/user/login",
-				protocol = "tlsv1",
-				method = "POST",
-				source = ltn12.source.string(body),
-				sink = ltn12.sink.table(res),
-				headers = headers }
-
-	local one, code, headers, status = https.request(url)
-
-	if (code == 200) then
-		res = json.decode(table.concat(res))
-
-		data.transport_url = res.urls.transport_url
-		data.userid = res.userid
-		data.access_token = res.access_token
-
-		task("Successful nest.com login.", TASK_SUCCESS)
-		saveSession(data.transport_url, data.userid, data.access_token)
-		return data
-	else
-		task("Failed to login: code=" .. tostring(code) .. ", status=" .. tostring(status))
-		clearSession()
-	end
-end
-
-local function getPackageVersion()
-	debug("getPackageVersion", "Verifying packages...")
-	local REQUIRED_VERSION = { '1', '0', '1', 'e', '1' }
-	local stdout = io.popen("opkg list-installed | awk '/openssl-util/ {print $3}'")
-	local version = stdout:read("*a")
-	version = version:match("([^%s]+)")
-	stdout:close()
-	local i = 1
-	for c in version:gmatch("[^.-]") do
-			if c < REQUIRED_VERSION[i] then
-				os.execute ("opkg install 'http://downloads.openwrt.org/attitude_adjustment/12.09/ramips/rt3883/packages/openssl-util_1.0.1e-1_ramips.ipk'")
-				debug("(Bosch Plugin)::(getPackageVersion) : Updating openssl-util!!!")
-			end
-			i = i + 1
-	end
-	REQUIRED_VERSION = { '0', '5', '5'}
-	stdout = io.popen("opkg list-installed | awk '/luasec/ {print $3}'")
-	version = stdout:read("*a")
-	version = version:match("([^%s]+)")
-	stdout:close()
-	i = 1
-	for c in version:gmatch("[^.-]") do
-			if c < REQUIRED_VERSION[i] then
-				os.execute ("opkg update")
-				os.execute ("opkg install luasec")
-				debug("(Bosch Plugin)::(getPackageVersion) : Updating luasec!!!")
-			end
-			i = i + 1
-	end
-	REQUIRED_VERSION = { '1', '0', '1', 'g', '1' }
-	stdout = io.popen("opkg list-installed | awk '/libopenssl/ {print $3}'")
-	version = stdout:read("*a")
-	version = version:match("([^%s]+)")
-	stdout:close()
-	i = 1
-	for c in version:gmatch("[^.-]") do
-			if c < REQUIRED_VERSION[i] then
-				os.execute ("opkg install 'http://downloads.openwrt.org/attitude_adjustment/12.09/ramips/rt3883/packages/libopenssl_1.0.1g-1_ramips.ipk'")
-				debug("(Bosch Plugin)::(getPackageVersion) : Updating libopenssl!!!")
-			end
-			i = i + 1
-	end
-	debug("(Bosch Plugin)::(getPackageVersion) : Packages OK")
 end
 
@@ -266,8 +122,352 @@
 	return s
 end
+
+local function getTemperatureScale()
+	local code, data = luup.inet.wget("http://localhost:3480/data_request?id=lu_sdata")
+	if (code == 0) then
+		data = dkjson.decode(data)
+	end
+	temperatureScale = ((code == 0) and (data ~= nil) and (data.temperature ~= nil)) and string.lower(data.temperature) or "f"
+end
+
+local function getNestDeviceID(device, data_structure)
+	for k,v in pairs (data_structure) do
+		if v.vera_id == device then
+			return v.device_id
+		end
+	end
+	return
+end
+
+local function nestRequest(method, headers, URL, data)
+	--debug("nestRequest","method = " .. method)
+	--debug("nestRequest","headers = " .. tostring(headers))
+	--debug("nestRequest","URL = " .. URL)
+	--debug("nestRequest","URL = " .. URL)
+	local curlCommand = ""
+	if method == "GET" or method == "POST" then
+		curlCommand = "curl -k -L -X " .. method .. " " .. headers .. " " .. URL
+	elseif method == "STREAM" then
+		curlCommand = "curl -N -k -v -L " .. URL .. " " .. headers .. " > /tmp/NestOutput.txt &" 
+	else
+		curlCommand = "curl -k -v -L -X " .. method .. " " .. URL .. " " .. headers .. " " .. data
+	end
+	--debug("nestRequest", "curlCommand = " .. tostring(curlCommand))
+	local stdout = io.popen(curlCommand)
+	local response = stdout:read("*a")
+	stdout:close()	
+		--debug("nestRequest", "curlCommand Response = [" .. tostring(response) .. "]")
+	
+	if method == "STREAM" then
+		local fileCreated = io.open("/tmp/NestOutput.txt")
+		if fileCreated then
+			return true
+		else
+			return
+		end
+	end
+	
+	if response and response ~= "" then
+		local json_string = response
+		local json_response = dkjson.decode(response)
+		local data = {}
+		if json_response.error then
+			debug("nestRequest", "error = " .. tostring(json_response.error))
+			debug("nestRequest", "description = " .. tostring(json_response.error_description))
+			return
+		else
+			return json_response, json_string
+		end
+		--[[
+		for k,v in pairs(response) do
+			log("get_token","key = [" .. tostring(k) .. "] and value = [" .. v .. "]")
+		end
+		-- ]]
+		return response
+	else
+		debug("nestRequest", "Empty response!")
+		return
+	end
+end
+
+local function get_token()
+end
+
+local function clearNestOutputFile()
+	local stdout = io.popen("ps | grep 'curl -N -k -v -L https://developer-api.nest.com/devices.json?auth=' | grep -v 'grep'")
+	local response = stdout:read("*a")
+	stdout:close()
+	response = response:gmatch("(%d+) root")
+	for v in response do
+		debug("clearNestOutputFile", "Killed process " .. v)
+		os.execute("kill " .. v)
+	end
+	os.execute("rm /tmp/NestOutput.txt")
+end
+
+local function startStreaming()
+	clearNestOutputFile()
+	local url = g_URL .. "/devices.json?auth=" .. nest_token
+	local header = "-H \"Accept: text/event-stream\" "
+	local response, response_string = nestRequest("STREAM", header, url, "")
+	if response then
+		debug("startStreaming", "Streaming started successful!")
+	else
+		--debug("startStreaming", "Nest Data = " .. response_string)
+		debug("startStreaming", "ERROR : Could not start Stream!")
+	end
+end
+
+function getStreamEvents()
+	debug("getStreamEvents", "Getting Stream Events ...")
+	local lfs = require "lfs"
+	local fileSize = lfs.attributes("/tmp/NestOutput.txt", "size")
+	debug("getStreamEvents", "File size is = [" .. tostring(fileSize) .. "]")
+		
+	-- check for new stram events
+	if fileSize then
+		if fileSize > g_fileSize then
+			local file = io.open("/tmp/NestOutput.txt")
+			file:seek("set", g_fileSize)
+			local newEvent = file:read("*a")
+			file:close()
+			newEvent = newEvent:match("data: (.*)}")
+			debug("getStreamEvents", "newEvent = [" .. tostring(newEvent) .. "]")
+			g_fileSize = fileSize
+			if newEvent and newEvent ~= "null" then
+				local response = dkjson.decode(newEvent .. "}")
+				local therm = response.data.thermostats
+				--[[
+				for key,val in pairs(therm) do
+					for k,v in pairs(val) do
+						debug("getStreamEvents","therm[" .. key .."][" .. tostring(k) .. "]=[" .. tostring(v) .. "]")
+					end
+				end	
+				]]
+				if therm then
+					for i=1,#g_thermostats do
+						if g_thermostats[i].device_id == therm[g_thermostats[i].device_id].device_id then
+							for k,v in pairs(therm[g_thermostats[i].device_id]) do
+								if v ~= g_thermostats[i][k] then
+									g_thermostats[i][k] = v
+									flagThermostat = true
+									debug("getStreamEvents", "updating g_thermostats[" .. i .. "][" .. k .. "] with value =" .. tostring(v))
+								end
+							end
+						end
+					end
+				end
+				debug("getStreamEvents", "Verifying Smoke and CO detector/s!")
+				local smokePoll = response.data.smoke_co_alarms
+				--[[
+				for key, val in pairs(smokePoll) do
+					for k,v in pairs(val) do
+						debug("getStreamEvents","smokePoll[" .. key .."][" .. tostring(k) .. "]=[" .. tostring(v) .. "]")
+					end
+				end	
+				]]
+				if smokePoll then
+					for i=1,#g_smoke do
+						if g_smoke[i].device_id == smokePoll[g_smoke[i].device_id].device_id then
+							for k,v in pairs(smokePoll[g_smoke[i].device_id]) do
+								if v ~= g_smoke[i][k] then
+									g_smoke[i][k] = v
+									flagSmoke = true
+									debug("getStreamEvents", "updating g_smoke[" .. i .. "][" .. k .. "] with value =" .. tostring(v))
+								end
+							end
+						end
+					end
+				end
+			end -- if newEvent
+			if flagThermostat then
+				updateThermostatValues()
+			end
+			if flagSmoke then
+				--updateSmokeValues()
+			end
+		end -- if fileSize > g_fileSize
+	end
+	-- check file size and delete if needed
+	if tonumber(fileSize) > g_maxFileSize then
+		-- delete /tmp/NestOutput.txt file & restart streaming
+		startStreaming()
+		debug("getStreamEvents", "Restarting Streaming!")
+	end
+	luup.call_delay("getStreamEvents", POLLING_RATE)
+end
+
+local function getNestData()
+	local url = g_URL .. "?auth=" .. nest_token
+	local header = "-H 'Accept: application/json'"
+	local response, response_string = nestRequest("GET", header, url, "")
+	if not response then
+		debug("getNestData", "ERROR : Could not get Nest Data!")
+	else
+		debug("getNestData", "Nest Data = " .. response_string)
+		if response.devices.thermostats then
+			local count = 1
+			g_thermostats[count] = {}
+			for k,v in pairs(response.devices.thermostats) do
+				g_thermostats[count].device_id = v.device_id
+				g_thermostats[count].name = v.name
+				g_thermostats[count].name_long = v.name_long
+				g_thermostats[count].locale = v.locale
+				g_thermostats[count].structure_id = v.structure_id
+				g_thermostats[count].software_version = v.software_version
+				g_thermostats[count].is_online = v.is_online
+				g_thermostats[count].last_connection = v.last_connection
+				g_thermostats[count].can_cool = v.can_cool
+				g_thermostats[count].can_heat = v.can_heat
+				g_thermostats[count].is_using_emergency_heat = v.is_using_emergency_heat
+				g_thermostats[count].has_fan = v.has_fan
+				g_thermostats[count].fan_timer_active = v.fan_timer_active
+				g_thermostats[count].fan_timer_timeout = v.fan_timer_timeout
+				g_thermostats[count].has_leaf = v.has_leaf
+				g_thermostats[count].temperature_scale = v.temperature_scale
+				g_thermostats[count].target_temperature_f = v.target_temperature_f
+				g_thermostats[count].target_temperature_c = v.target_temperature_c
+				g_thermostats[count].target_temperature_high_f = v.target_temperature_high_f
+				g_thermostats[count].target_temperature_high_c = v.target_temperature_high_c
+				g_thermostats[count].target_temperature_low_f = v.target_temperature_low_f
+				g_thermostats[count].target_temperature_low_c = v.target_temperature_low_c
+				g_thermostats[count].away_temperature_high_f = v.away_temperature_high_f
+				g_thermostats[count].away_temperature_high_c = v.away_temperature_high_c
+				g_thermostats[count].away_temperature_low_f = v.away_temperature_low_f
+				g_thermostats[count].away_temperature_low_c = v.away_temperature_low_c
+				g_thermostats[count].hvac_mode = v.hvac_mode
+				g_thermostats[count].ambient_temperature_f = v.ambient_temperature_f
+				g_thermostats[count].ambient_temperature_c = v.ambient_temperature_c
+				g_thermostats[count].humidity = v.humidity
+				count = count + 1
+			end
+		end
+		if response.devices.smoke_co_alarms then
+			local count = 1
+			g_smoke[count] = {}
+			for k,v in pairs(response.devices.smoke_co_alarms) do
+				g_smoke[count].name = v.name
+				g_smoke[count].name_long = v.name_long
+				g_smoke[count].locale = v.locale
+				g_smoke[count].structure_id = v.structure_id
+				g_smoke[count].software_version = v.software_version
+				g_smoke[count].device_id = v.device_id
+				g_smoke[count].is_online = v.is_online
+				g_smoke[count].last_connection = v.last_connection
+				g_smoke[count].battery_health = v.battery_health
+				g_smoke[count].co_alarm_state = v.co_alarm_state
+				g_smoke[count].smoke_alarm_state = v.smoke_alarm_state
+				g_smoke[count].ui_color_state = v.ui_color_state
+				count = count + 1
+			end
+		end
+		if response.devices.structures then
+			local count = 1
+			g_structures[count] = {}
+			for k,v in pairs(response.structures) do
+				g_structures[count].structure_id = v.structure_id
+				g_structures[count].thermostats = v.thermostats
+				g_structures[count].smoke_co_alarms = v.smoke_co_alarms
+				g_structures[count].name = v.name
+				g_structures[count].away = v.away
+				-- [[
+				g_structures[count].is_online = v.is_online
+				g_structures[count].last_connection = v.last_connection
+				g_structures[count].battery_health = v.battery_health
+				g_structures[count].co_alarm_state = v.co_alarm_state
+				g_structures[count].smoke_alarm_state = v.smoke_alarm_state
+				g_structures[count].ui_color_state = v.ui_color_state
+				-- ]]
+				count = count + 1
+			end
+		end
+	end
+end
+
+local function loginToNest(device, username, password)
+	
+	local url = "https://home.nest.com/user/login"
+	local curlCommand = "curl -k --data 'username=" .. g_username .. "&password=" ..g_password .. "' https://home.nest.com/user/login"
+	log("loginToNest", "curlCommand = " .. tostring(curlCommand))
+	local stdout = io.popen(curlCommand)
+	local response = stdout:read("*a")
+	stdout:close()	
+	log("loginToNest", "curlCommand Response = " .. tostring(response))
+	local json_response = dkjson.decode(response)
+	local data = {}
+	if json_response.error then
+		log("loginToNest", "error = " .. json_response.error)
+		log("loginToNest", "description = " .. json_response.error_description)
+    else
+		data.transport_url = json_response.urls.transport_url
+        data.userid = json_response.userid
+        data.access_token = json_response.access_token
+    end
+	log("loginToNest","data.transport_url = [" .. data.transport_url .. "]" )
+	log("loginToNest","data.userid = [" .. data.userid .. "]" )
+	log("loginToNest","data.access_token = [" .. data.access_token .. "]" )
+	url = "https://developer-api.nest.com/?auth=" .. data.access_token
+	log("loginToNest","URL = [" .. url .. "]" )
+	curlCommand = "curl -k -L -X GET -H 'Accept: application/json '" .. url
+	log("loginToNest", "curlCommand2 = " .. tostring(curlCommand))
+	stdout = io.popen(curlCommand)
+	response = stdout:read("*a")
+	stdout:close()	
+	log("loginToNest", "curlCommand2 Response = " .. tostring(response))
+	local json_response = dkjson.decode(response)
+end
 ---------------------------------------------------------
 ---------------System Command Group----------------------
 ---------------------------------------------------------
-
+local function updateThermostatValues()
+	debug("updateThermostatValues","Verifying... ")
+	local CurrentTemperature = 0
+	local CurrentSetpoint = 0
+	local SetpointTarget = 0
+	local ModeStatus = ""
+	local CurrentHumidity = 0
+	for key, value in pairs(g_thermostats) do
+		CurrentTemperature = tostring(value["ambient_temperature_" .. temperatureScale])
+		CurrentSetpoint = tostring(value["target_temperature_" .. temperatureScale])
+		ModeStatus = tostring(value.hvac_mode)
+		CurrentHumidity = value.humidity
+		if ModeStatus == "heat" then
+			ModeStatus = "HeatOn"
+		elseif ModeStatus == "cool" then
+			ModeStatus = "CoolOn"
+		elseif ModeStatus == "heat-cool" then
+			ModeStatus = "AutoChangeOver"
+		elseif ModeStatus == "off" then
+			ModeStatus = "Off"
+		end
+		
+		local AllSetpoints = CurrentSetpoint .. "," .. CurrentSetpoint .. ",0"
+		--debug("updateThermostatValues","CurrentTemperature = " .. tostring(CurrentTemperature) .. " CurrentSetpoint = " .. tostring(CurrentSetpoint) .. " AllSetpoints = " .. tostring(AllSetpoints))
+		--debug("updateThermostatValues","DEVICE ID = " .. tostring(value.vera_id))
+		
+		local ModeStatusUI = luup.variable_get("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", tonumber(value.vera_id)) or ""
+		local CurrentSetpointUI = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", tonumber(value.vera_id)) or ""
+		local CurrentTemperatureUI = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", tonumber(value.vera_id)) or ""
+		local HumidityUI = luup.variable_get("urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", tonumber(value.vera_id)) or ""
+		
+		if ModeStatus ~= ModeStatusUI then
+			luup.variable_set("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", ModeStatus, tonumber(value.vera_id))
+		end
+		if CurrentSetpoint ~= CurrentSetpointUI then
+			luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", CurrentSetpoint, tonumber(value.vera_id))
+			luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "AllSetpoints", AllSetpoints, tonumber(value.vera_id))
+		end
+		if CurrentTemperature ~= CurrentTemperatureUI then
+			luup.variable_set("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", CurrentTemperature, tonumber(value.vera_id))
+		end
+		if tonumber(HumidityUI) ~= CurrentHumidity then
+			luup.variable_set("urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", CurrentHumidity ,tonumber(value.humidityDevice_id))
+		end
+	end
+end
+
+local function updateSmokeValues()
+
+end
 ---------------------------------------------------------
 ---------------Action Implementations--------------------
@@ -277,8 +477,73 @@
 		luup.task("Clearing...", TASK.SUCCESS, "BoschPlugin", g_taskHandle)
 	end
-	debug("(Bosch Plugin)::(clearTask) : Clearing task... ")
-end
-
-
+	debug("clearTask", "Clearing task... ")
+end
+
+function setModeTarget(device, mode)
+	local VeraMode = mode
+	if mode == "HeatOn" then 
+		mode = "heat"
+	elseif mode == "CoolOn" then
+		mode = "cool"
+	elseif mode == "AutoChangeOver" then
+		mode = "heat-cool"
+	elseif mode == "Off" then
+		mode = "off"
+	end
+	
+	local thermostatID = getNestDeviceID(device, g_thermostats)
+	
+	--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"}'
+	local url = g_URL .. "/devices/thermostats/" .. tostring(thermostatID) .. "?auth=" .. nest_token
+	local header = "-H 'Content-Type: application/json'"
+	local data = "-d '{\"hvac_mode\" : \"" .. mode .."\" }'"
+	log("setModeTarget", "data = " .. data)
+	local response, response_string = nestRequest("PUT", header, url, data)
+	if not response then
+		log("setModeTarget", "ERROR : Could not set Data!")
+	else
+		log("setModeTarget", "Nest Response = " .. response_string)
+		luup.variable_set("urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", VeraMode, device)
+	end
+end
+
+function setCurrentSetpoint(device, value)
+	local thermostatID = getNestDeviceID(device, g_thermostats)
+	
+	if tonumber(value) > 32 then
+		value = "32"
+	end
+	--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"}'
+	local url = g_URL .. "/devices/thermostats/" .. tostring(thermostatID) .. "?auth=" .. nest_token
+	local header = "-H 'Content-Type: application/json'"
+	local data = "-d '{\"target_temperature_" .. temperatureScale .. "\" :" .. tonumber(value) .. "}'"
+	log("setCurrentSetpoint", "data = " .. data)
+	local response, response_string = nestRequest("PUT", header, url, data)
+	if not response then
+		log("setCurrentSetpoint", "ERROR : Could not set Data!")
+	else
+		log("setCurrentSetpoint", "Request OK, Response = " .. response_string)
+		local all = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1", "AllSetpoints", device) or ""
+		local now = luup.variable_get("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", device) or ""
+		all = string.gsub( all, now, value, 1 )
+		log("setCurrentSetpoint", "ALL = [" .. all .. "]")
+		luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "AllSetpoints", all, device)
+		luup.variable_set("urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", value, device)
+	end
+end
+
+function setArmed(device, value)
+	luup.variable_set(SID.SES, "Armed", value, device)
+end
+
+function setTarget(device, value)
+	luup.variable_set(SID.SWP, "Status", value, device)
+	luup.variable_set(SID.SWP, "Target", value, device)
+end
+
+function connectWithNest(device, username, password)
+	log("connectWithNest", "AM AJUNS!!!!")
+	loginToNest(device, username, password)
+end
 ---------------------------------------------------------
 ---------------Initialization Functions------------------
@@ -287,70 +552,57 @@
 	for dev, attr in pairs(luup.devices) do
 		if (attr.device_num_parent == device) then
-			local zoneNo = attr.id:match("^bosch_point_(%d+)")
-			local partitionNo = attr.id:match("^bosch_area_(%d+)")
-			local outputNo = attr.id:match("^bosch_output_(%d+)_")
-			for k,v in pairs(g_areas) do
-				if partitionNo == tostring(v.panelID) then
-					partitionNo = tostring(k)
-				end
-			end
-			if (zoneNo ~= nil) then
-				zoneNo = tonumber(zoneNo, 10)
-				g_points[zoneNo].devId = dev
-			elseif (partitionNo ~= nil) then
-					partitionNo = tonumber(partitionNo, 10)
-					g_areas[partitionNo].devId = dev
-			else
-				if (outputNo ~= nil) then
-					outputNo = tonumber(outputNo, 10)
-					for key,val in pairs(g_outputs) do
-						if outputNo == tonumber(val.panelID) then
-							g_outputs[key].devId = dev
-						end
+			local thermostatID = attr.id:match("^nest_thermostat_(.+)")
+			local smokeID = attr.id:match("^nest_sco_(.+)")
+			local humidity = attr.id:match("^nest_humidity_(.+)")
+			if thermostatID then
+				for k,v in pairs(g_thermostats) do
+					if thermostatID == tostring(v.device_id) then
+						g_thermostats[tonumber(k)].vera_id = dev
 					end
 				end
 			end
-		end
-	end
-end
-
-local function appendPoints()
-	local count = 0
-	for i, v in ipairs(g_points) do
-		debug("(Bosch Plugin)::(appendPoints) : Appending zone ".. i ..".")
-		local device = getDeviceType(i)
-		luup.chdev.append(lug_device, g_appendPtr, "bosch_point_"..i, "Point ".. i ..": ".. v.label, device.type, device.file, nil, nil, false)
-		if count > 20 then
-			debug("(Bosch Plugin)::(appendPoints) : Possible error in generating points, more then 20 devices were generated!!!")
-			FLAGS.ZONES = true
-			return
-		end
-	end
-	FLAGS.ZONES = true
-end
-
-local function appendAreas()
-	local count = 0
-	for i, v in ipairs(g_areas) do
-		debug("(Bosch Plugin)::(appendAreas) : Appending partition ".. i ..".")
-		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)
+			if smokeID then
+				for k,v in pairs(g_smoke) do
+					if smokeID == tostring(v.device_id) then
+						g_smoke[tonumber(k)].vera_id = dev
+					end
+				end
+			end
+			if humidity then
+				for k,v in pairs(g_thermostats) do
+					if humidity == tostring(v.device_id) then
+						g_thermostats[tonumber(k)].humidityDevice_id = dev
+					end
+				end
+			end
+		end
+	end
+end
+
+
+local function appendDevices()
+	local count  = 0
+	for k, v in ipairs(g_thermostats) do
+		debug("appendDevices", "Appending thermostat ".. v.name ..".")
+		luup.chdev.append(lug_device, g_appendPtr, "nest_thermostat_".. v.device_id, v.name, DEVICE_TYPES.THERMOSTAT, DEVICE_FILES.THERMOSTAT, nil, nil, false)
+		debug("appendDevices", "Appending Home/Away ".. v.name ..".")
+		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)
+		if v.humidity then
+			debug("appendDevices", "Appending humidity ".. v.name ..".")
+			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)
+		end
 		count = count + 1
 		if count > 20 then
-			debug("(Bosch Plugin)::(appendAreas) : Possible error in generating areas, more then 20 devices were generated!!!")
-			FLAGS.PARTITIONS = true
+			debug("appendDevices", "Possible error in generating outputs, more then 20 devices were generated!!!")
 			return
 		end
 	end
-	FLAGS.PARTITIONS = true
-end
-
-local function appendOutputs()
-	local count  = 0
-	for i, v in ipairs(g_outputs) do
-		debug("(Bosch Plugin)::(appendOutputs) : Appending output ".. v.name ..".")
-		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)
+	
+	for k, v in ipairs(g_smoke) do
+		debug("appendDevices", "Appending smoke sensor ".. v.name ..".")
+		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)
 		count = count + 1
 		if count > 20 then
-			debug("(Bosch Plugin)::(appendOutputs) : Possible error in generating outputs, more then 20 devices were generated!!!")
+			debug("appendDevices", "Possible error in generating outputs, more then 20 devices were generated!!!")
 			return
 		end
@@ -359,164 +611,99 @@
 
 local function getInfos(device)
-	local debugMode = luup.variable_get(SID.BOSCH, "DebugMode", device) or ""
+	
+	local flagError = false
+	
+	local debugMode = luup.variable_get(SID.NEST, "DebugMode", device) or ""
 	if (debugMode ~= "") then
 		DEBUG_MODE = (debugMode == "1") and true or false
 	else
-		luup.variable_set(SID.BOSCH, "DebugMode", (DEBUG_MODE and "1" or "0"), device)
-	end
-	log("(Bosch Plugin)::(getDebugMode) : Debug mode "..(DEBUG_MODE and "enabled" or "disabled")..".")
-
-	local polling_rate = luup.variable_get(SID.BOSCH, "POLLING_RATE", device) or ""
+		luup.variable_set(SID.NEST, "DebugMode", (DEBUG_MODE and "1" or "0"), device)
+	end
+	log("getInfos", "Debug mode "..(DEBUG_MODE and "enabled" or "disabled")..".")
+
+	local polling_rate = luup.variable_get(SID.NEST, "POLLING_RATE", device) or ""
 	if (polling_rate ~= "") then
 		POLLING_RATE = tonumber(polling_rate)
 	else
-		luup.variable_set(SID.BOSCH, "POLLING_RATE", POLLING_RATE, device)
-	end
-	debug("(Bosch Plugin)::(getDebugMode) : POLLING_RATE = " .. POLLING_RATE )
-	
-	local safestorage = luup.variable_get(SID.BOSCH,"SafeStorage",lug_device) or ""
-	if safestorage == "" then
-		luup.variable_set(SID.BOSCH,"SafeStorage","0",lug_device)
-	end
-	
-	local passcode = luup.variable_get(SID.BOSCH,"Passcode",lug_device) or ""
-	if passcode == "" then 
-		luup.variable_set(SID.BOSCH,"Passcode","Bosch_Auto",lug_device)
-	end
-	
-	local trash
-	ipAddress, trash, ipPort = string.match(luup.devices[device].ip, "^([%w%.%-]+)(:?(%d-))$")
-	if ipAddress and ipAddress ~= "" then
-		if ipPort==nil or ipPort == "" then
-			ipPort = "7700"
-		end
-		return true
-	else
-		log("(Bosch Plugin)::(getDebugMode) : ERROR : Insert IP address!")
-		return false
-	end
-end
-
-
-local function connectToPanel()
-	local retry
-	local i
-	local flagConnect = false
-	local flagPass = false
-	local passcode
-	
-	local safestorage = luup.variable_get(SID.BOSCH,"SafeStorage",lug_device) or ""
-	if safestorage == "" then
-		luup.variable_set(SID.BOSCH,"SafeStorage","0",lug_device)
-		safestorage = "0"
-	end
-
-	if safestorage == "0" then
-		passcode = luup.variable_get(SID.BOSCH,"Passcode",lug_device) or ""
-		if passcode == "" then
-			luup.variable_set(SID.BOSCH,"Passcode","Bosch_Auto",lug_device)
-			log("(Bosch Plugin)::(connectToPanel) : ERROR : Password field have a default value!")
-			displayMessage("Password field have a default value!", TASK.ERROR)
+		luup.variable_set(SID.NEST, "POLLING_RATE", POLLING_RATE, device)
+	end
+	debug("getInfos", "POLLING_RATE = " .. POLLING_RATE )
+	
+	local username = luup.devices[device].user or ""
+	local password = luup.devices[device].pass or ""
+	
+	getTemperatureScale()
+	log("getInfos", "Temperature Scale is = " .. temperatureScale)
+	
+	if username == "" then
+		luup.attr_set("username","default",device)
+		g_username = "default"
+		flagError = true
+	else
+		if username == "default" then
+			flagError = true
+		else 
+			g_username = username
+		end
+	end
+
+	if password == "" then
+		luup.attr_set("password","default",device)
+		g_password = "default"
+		flagError = true
+	else
+		if password == "default" then
+			flagError = true
 		else
-			g_passcode = passcode
-			flagPass = true
-		end
-	elseif safestorage == "1" then
-		local file = io.open("/tmp/credential.txt")
-		if file then
-			for line in file:lines() do
-				passcode = line:match('^(.-)$')
-			end
-			file:close()
-			if passcode then
-				g_passcode = passcode
-				flagPass = true
-			else
-				log("(Bosch Plugin)::(connectToPanel) : ERROR : Please insert your passcode in file!")
-				displayMessage("Please insert your passcode in file!", TASK.ERROR)
-			end
-		else
-			log("(Bosch Plugin)::(connectToPanel) : ERROR : Couldn't open passcode file!")
-			displayMessage("Couldn't open passcode file!", TASK.ERROR)
-		end
-	else
-		log("(Bosch Plugin)::(connectToPanel) : ERROR : Invalid SafeStorage value. Please insert a valid one(0 or 1)!")
-		displayMessage("Invalid SafeStorage value. Please insert a valid one(0 or 1)!", TASK.ERROR)
-	end
-
-	if flagPass then
-		for i = 1, 10 do
-			retry =  peer:connect(ipAddress, ipPort)
-			if retry then
-				flagConnect = true
-				break
-			else
-				debug("(Bosch Plugin)::(connectToPanel) : ERROR : Cannot connect to panel!")
-			end
-		end
-		if flagConnect then
-			peer = assert( ssl.wrap(peer, params) )
-			peer:settimeout(0.3)
-
-			local succ, err = peer:dohandshake()
-			while not succ do
-				wait(peer, err)
-				succ, err = peer:dohandshake()
-			end
-			debug("*** Handshake done ***")
-			local responseArray = {}
-			local responseString
-			responseString = WhatAreYou()
-			if responseString then
-				responseArray = parse(responseString,{})
-			else
-				debug("(Bosch Plugin)::(connectToPanel) : ERROR : Handshake ERROR!")
-			end
-			responseString = PasscodeAndUserTypeCheck(g_passcode)
-			if responseString then
-				responseArray = parse(responseString,{})
-				if responseArray[3] == "FE" then
-					if responseArray[4] == "00" then
-						log("(Bosch Plugin)::(connectToPanel) : ERROR :  Passcode and User Type Check ERROR! Another Session is opened, cannot authentify !")
-						flagPasscode = false
-					elseif responseArray[4] == "01" then
-						log("(Bosch Plugin)::(connectToPanel) : OK :  Passcode and User Type Check OK! continuing ...")
-						flagPasscode = true
-					else
-						log("(Bosch Plugin)::(connectToPanel) : ERROR :  Unknown Passcode and User Type Check ERROR! FE : [" .. responseArray[4] .. "]")
-						flagPasscode = false
-					end
-				elseif responseArray[3] == "FD" then
-					log("(Bosch Plugin)::(connectToPanel) : ERROR :  NAK received with error code " .. responseArray[4])
-					flagPasscode = false
-				elseif responseArray[3] == "FC" then
-					log("(Bosch Plugin)::(connectToPanel) : ERROR :  ACK received")
-					flagPasscode = false
-				else
-					log("(Bosch Plugin)::(connectToPanel) : ERROR :  Unknown ERROR (we should not be here)")
-					flagPasscode = false
-				end
-			else
-				log("(Bosch Plugin)::(connectToPanel) ERROR : PasscodeAndUserTypeCheck error!")
-			end
-		else
-			log("(Bosch Plugin)::(connectToPanel) : ERROR : Please check IP and PORT settings!")
-			displayMessage("Please check IP and PORT settings!", TASK.ERROR_STOP)
-		end
-	else
-		log("(Bosch Plugin)::(connectToPanel) : ERROR : Please check Passcode settings!")
-		displayMessage("Please check Passcode settings!", TASK.ERROR)
-	end
-end
-
+			g_password = password
+		end
+	end
+	
+	local token = luup.variable_get(SID.NEST, "TOKEN", device) or ""
+	if token ~= "" and token ~= "default" then
+		nest_token = token
+	else
+		luup.variable_set(SID.NEST, "TOKEN", "default", device)
+	end
+	return flagError
+end
 
 function Init(lul_device)
-
 	lug_device = lul_device
 	g_taskHandle = luup.task("Starting up...", TASK.BUSY, "Vera Connect WWN", g_taskHandle)
+	local continue = getInfos(lug_device)
+	if continue then
+		return false, "Username and/or password not set. Please add them in 'Advance' tab!", "Vera Connect WWN"
+	end
+	getNestData()
+	g_appendPtr = luup.chdev.start(lug_device)
+	appendDevices(lug_device)
+	luup.chdev.sync(lug_device, g_appendPtr)
+	getChildDevices(lug_device)
+	log("Init", "Updating thermostat values!")
+	updateThermostatValues()
+	log("Init", "Trying to start streaming and get the latest event/s!")
+	startStreaming()
+	getStreamEvents()
+	-------------------------------
+	for i=1,#g_thermostats do
+		for k,v in pairs(g_thermostats[i]) do
+			log("Init","g_thermostats[".. i .."].[" .. tostring(k) .. "]=[" .. tostring(v) .. "]")
+		end
+	end	
+	for i=1,#g_smoke do
+		for k,v in pairs(g_smoke[i]) do
+			log("Init","g_smoke[".. i .."].[" .. tostring(k) .. "]=[" .. tostring(v) .. "]")
+		end
+	end	
+	for i=1,#g_structures do
+		for k,v in pairs(g_structures[i]) do
+			log("Init","g_structures[".. i .."].[" .. tostring(k) .. "]=[" .. tostring(v) .. "]")
+		end
+	end	
+	------------------------------
 	log( "Startup", "Startup Successful" )
 	g_taskHandle = luup.task("Startup successful.", TASK.BUSY, "Vera Connect WWN", g_taskHandle)
 	luup.set_failure(0, lul_device)
 	return true, "Startup successful.", "Vera Connect WWN"
-	
-end
+end
Index: /trunk/D_VeraConnectWWN1.json
===================================================================
--- /trunk/D_VeraConnectWWN1.json	(revision 1)
+++ /trunk/D_VeraConnectWWN1.json	(revision 3)
@@ -15,4 +15,5 @@
 			"Position": "0",
 			"TabType": "flash",
+			"top_navigation_tab" : 1,
 			"SceneGroup":[
 				{
@@ -35,10 +36,10 @@
 					"ControlType": "label",
 					"Label": {
-						"lang_tag": "list_zones",
-						"text": "Points:"
+						"lang_tag": "username_label",
+						"text": "Userame : "
 					},
 					"Display": {
 						"Top": 20,
-						"Left": 70,
+						"Left": 40,
 						"Width": 75,
 						"Height": 20
@@ -47,9 +48,32 @@
 				{
 					"ControlType": "input",
-					"ID": "ListVal",
+					"ID": "username",
 					"Display": {
-						"Top": 40,
-						"Left": 70,
+						"Top": 20,
+						"Left": 130,
+						"Width":100,
+						"Height": 20
+					}
+				},
+				{
+					"ControlType": "label",
+					"Label": {
+						"lang_tag": "password_label",
+						"text": "Password : "
+					},
+					"Display": {
+						"Top": 50,
+						"Left": 40,
 						"Width": 75,
+						"Height": 20
+					}
+				},
+				{
+					"ControlType": "input",
+					"ID": "password",
+					"Display": {
+						"Top": 50,
+						"Left": 130,
+						"Width": 100,
 						"Height": 20
 					}
@@ -58,10 +82,10 @@
 					"ControlType": "button",
 					"Label": {
-						"lang_tag": "button_bypass",
-						"text": "Bypass"
+						"lang_tag": "button_connect",
+						"text": "Connect with Nest"
 					},
 					"Display": {
-						"Top": 70,
-						"Left": 70,
+						"Top": 80,
+						"Left": 40,
 						"Width": 60,
 						"Height": 20
@@ -69,32 +93,13 @@
 					"Command": {
 						"Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1",
-						"Action": "SendBypassPoints",
+						"Action": "ConnectWithNest",
 						"Parameters": [
 							{
-								"Name": "List",
-								"ID": "ListVal"
-							}
-						]
-					}
-				},
-				{
-					"ControlType": "button",
-					"Label": {
-						"lang_tag": "button_activate",
-						"text": "Unbypass"
-					},
-					"Display": {
-						"Top": 95,
-						"Left": 70,
-						"Width": 60,
-						"Height": 20
-					},
-					"Command": {
-						"Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1",
-						"Action": "SendUnbypassPoints",
-						"Parameters": [
+								"Name": "Username",
+								"ID": "username"
+							},
 							{
-								"Name": "List",
-								"ID": "ListVal"
+								"Name": "Password",
+								"ID": "password"
 							}
 						]
@@ -104,137 +109,13 @@
 		},
 		{
-			"Label": {
-				"lang_tag": "history",
-				"text": "History"
-			},
-			"Position": "0",
-			"TabType": "flash",
-			"SceneGroup":[
-				{
-					"id": "1",
-					"top": "1",
-					"left": "0",
-					"x": "1",
-					"y": "1"
-				}
-			],
-			"ControlGroup": [
-				{
-					"id": "1",
-					"isSingle": "0",
-					"scenegroup": "1"
-				}
-			],
-			"Control": [
-				{
-					"ControlType": "label",
-					"Label": {
-						"lang_tag": "History_event_interval : ",
-						"text": "History event interval:"
-					},
-					"Display": {
-						"Top": 20,
-						"Left": 200,
-						"Width": 100,
-						"Height": 20
-					}
-				},
-				{
-					"ControlType": "variable",
-					"Display": {
-						"Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1",
-						"Variable": "Interval",
-						"Top": 20,
-						"Left": 340,
-						"Width": 75,
-						"Height": 20
-					}
-				},
-				{
-					"ControlType": "label",
-					"Label": {
-						"lang_tag": "start_event : ",
-						"text": "Start event number:"
-					},
-					"Display": {
-						"Top": 45,
-						"Left": 200,
-						"Width": 75,
-						"Height": 20
-					}
-				},
-				{
-					"ControlType": "input",
-					"ID": "startEventNo",
-					"Display": {
-						"Top": 70,
-						"Left": 200,
-						"Width": 75,
-						"Height": 20
-					}
-				},
-				{
-					"ControlType": "label",
-					"Label": {
-						"lang_tag": "number_of_events : ",
-						"text": "Number of events:"
-					},
-					"Display": {
-						"Top": 45,
-						"Left": 330,
-						"Width": 75,
-						"Height": 20
-					}
-				},
-				{
-					"ControlType": "input",
-					"ID": "numberOfEvents",
-					"Display": {
-						"Top": 70,
-						"Left": 330,
-						"Width": 75,
-						"Height": 20
-					}
-				},
-				{
-					"ControlType": "button",
-					"Label": {
-						"lang_tag": "get_history",
-						"text": "Get History"
-					},
-					"Display": {
-						"Top": 100,
-						"Left": 265,
-						"Width": 80,
-						"Height": 20
-					},
-					"Command": {
-						"Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1",
-						"Action": "GetHistory",
-						"Parameters": [
-							{
-								"Name": "EventNo",
-								"ID": "numberOfEvents"
-							},
-							{
-								"Name": "StartEvent",
-								"ID": "startEventNo"
-							}
-						]
-					}
-				},
-				{
-					"ControlType": "variable",
-					"left": "1",
-					"Display": {
-						"Service": "urn:micasaverde-com:serviceId:VeraConnectWWN1",
-						"Variable": "HistoryLog",
-						"Top": 140,
-						"Left": 200,
-						"Width": 200,
-						"Height": 200
-					}
-				}
-			]
+		  "Label": {
+			"lang_tag": "authorize",
+			"text": "Authorize"
+		  },
+		  "Position": "1",
+		  "TopNavigationTab": "1",
+		  "TabType": "javascript",
+		  "ScriptName": "J_VeraConnectWWN1.js",
+		  "Function": "VeraConnectWWN.init"
 		},
 		{
@@ -243,5 +124,5 @@
 				"text": "Advanced"
 			},
-			"Position": "1",
+			"Position": "2",
 			"TabType": "javascript",
 			"ScriptName": "shared.js",
Index: /trunk/S_VeraConnectWWN1.xml
===================================================================
--- /trunk/S_VeraConnectWWN1.xml	(revision 1)
+++ /trunk/S_VeraConnectWWN1.xml	(revision 3)
@@ -29,21 +29,18 @@
 	<actionList>
 		<action>
-			<name>StorePinCode</name>
+			<name>ConnectWithNest</name>
 			<argumentList>
 				<argument>
-					<name>PinCode</name>
+					<name>Username</name>
                     <direction>in</direction>
-                    <relatedStateVariable>ui4</relatedStateVariable>
+                    <relatedStateVariable>string</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Password</name>
+                    <direction>in</direction>
+                    <relatedStateVariable>string</relatedStateVariable>
 				</argument>
 			</argumentList>
 		</action>
-		<action>
-			<name>ClearPinCode</name>
-			<argumentList></argumentList>
-		</action>
-		<action>
-			<name>ClearTask</name>
-			<argumentList></argumentList>
-		</action>
 	</actionList>
 </scpd>
Index: /trunk/D_VeraConnectWWN1.xml
===================================================================
--- /trunk/D_VeraConnectWWN1.xml	(revision 1)
+++ /trunk/D_VeraConnectWWN1.xml	(revision 3)
@@ -18,4 +18,61 @@
 				<SCPDURL>S_VeraConnectWWN1.xml</SCPDURL>
 			</service>
+			<service>
+				<Optional/>
+				<serviceType>urn:schemas-upnp-org:service:HVAC_FanOperatingMode:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:HVAC_FanOperatingMode1</serviceId>
+				<SCPDURL>S_HVAC_FanOperatingMode1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:micasaverde-com:serviceId:HVAC_OperatingState:1</serviceType>
+				<serviceId>urn:micasaverde-com:serviceId:HVAC_OperatingState1</serviceId>
+				<SCPDURL>S_HVAC_OperatingState1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-upnp-org:service:HVAC_UserOperatingMode:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:HVAC_UserOperatingMode1</serviceId>
+				<SCPDURL>S_HVAC_UserOperatingMode1.xml</SCPDURL>
+			</service>
+			<service>
+				<Optional/>
+				<serviceType>urn:schemas-upnp-org:service:FanSpeed:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:FanSpeed1</serviceId>
+				<SCPDURL>S_FanSpeed1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-upnp-org:service:TemperatureSensor:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:TemperatureSensor1</serviceId>
+				<SCPDURL>S_TemperatureSensor1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-upnp-org:service:TemperatureSetpoint:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1</serviceId>
+				<SCPDURL>S_TemperatureSetpoint1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-upnp-org:service:TemperatureSetpoint:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1_Heat</serviceId>
+				<SCPDURL>S_TemperatureSetpoint1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-upnp-org:service:TemperatureSetpoint:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1_Cool</serviceId>
+				<SCPDURL>S_TemperatureSetpoint1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>
+				<serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId>
+				<SCPDURL>S_SwitchPower1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-micasaverde-com:service:EnergyMetering:1</serviceType>
+				<serviceId>urn:micasaverde-com:serviceId:EnergyMetering1</serviceId>
+				<SCPDURL>S_EnergyMetering1.xml</SCPDURL>
+			</service>
+			<service>
+				<serviceType>urn:schemas-micasaverde-com:service:HaDevice:1</serviceType>
+				<serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId>
+				<SCPDURL>S_HaDevice1.xml</SCPDURL>
+			</service>
 		</serviceList>
 		<implementationList>
Index: /trunk/I_VeraConnectWWN1.xml
===================================================================
--- /trunk/I_VeraConnectWWN1.xml	(revision 1)
+++ /trunk/I_VeraConnectWWN1.xml	(revision 3)
@@ -4,5 +4,5 @@
 		local fc = 0 -- failure counter
 		function VeraConnectWWNStartup (lul_device)
-			luup.log( "(Vera Connect WWN)::(Startup) : Initiating" )
+			luup.log( "(Vera Connect WWN)::(Startup) : Initiating..." )
 			package.loaded.L_Bosch1 = nil
 			nestPlugin = require( "L_VeraConnectWWN1" )
@@ -11,5 +11,11 @@
 			updateState = nestPlugin.updateState
 			setTarget = nestPlugin.setTarget
-			--reconnect = boschPlugin.reconnect
+			connectWithNest = nestPlugin.connectWithNest
+			pollNest = nestPlugin.pollNest
+			setModeTarget = nestPlugin.setModeTarget
+			setCurrentSetpoint = nestPlugin.setCurrentSetpoint
+			setMode = nestPlugin.setMode
+			setArmed = nestPlugin.setArmed
+			getStreamEvents = nestPlugin.getStreamEvents
 			
 			return nestPlugin.Init( lul_device )
@@ -29,5 +35,5 @@
 			<name>SetTarget</name>
 			<job>
-				setTarget( lul_settings.newTargetValue, lul_device )
+				setTarget(lul_device, lul_settings.newTargetValue)
 			</job>
 		</action>
@@ -39,4 +45,32 @@
 			</job>
 		</action>
+		<action>
+			<serviceId>urn:micasaverde-com:serviceId:VeraConnectWWN1</serviceId>
+			<name>ConnectWithNest</name>
+			<job>
+				connectWithNest (lul_device, lul_settings.username, lul_settings.password)
+			</job>
+		</action>
+		<action>
+			<serviceId>urn:upnp-org:serviceId:HVAC_UserOperatingMode1</serviceId>
+			<name>SetModeTarget</name>
+			<job>
+				setModeTarget (lul_device, lul_settings.NewModeTarget)
+			</job>
+		</action>
+		<action>
+			<serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1</serviceId>
+			<name>SetCurrentSetpoint</name>
+			<job>
+				setCurrentSetpoint (lul_device, lul_settings.NewCurrentSetpoint)
+			</job>
+		</action>
+		<action>
+			<serviceId>urn:upnp-org:serviceId:HVAC_FanOperatingMode1</serviceId>
+			<name>SetMode</name>
+			<job>
+				setMode (lul_device, lul_settings.NewMode)
+			</job>
+		</action>
 	</actionList>
 </implementation>
