Index: /tags/v0.1/S_TCPLightingGateway1.xml
===================================================================
--- /tags/v0.1/S_TCPLightingGateway1.xml	(revision 3)
+++ /tags/v0.1/S_TCPLightingGateway1.xml	(revision 3)
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <serviceStateTable>
+    <stateVariable sendEvents="yes">
+      <name>Initialized</name>
+      <dataType>boolean</dataType>
+      <defaultValue>0</defaultValue>
+    </stateVariable>
+    <stateVariable sendEvents="no">
+      <name>ErrorText</name>
+      <dataType>string</dataType>
+    </stateVariable>
+  </serviceStateTable>
+  <actionList>
+    <action>
+      <name>Synchronize</name>
+    </action>
+  </actionList>
+</scpd>
Index: /tags/v0.1/D_TCPLightingGateway1.xml
===================================================================
--- /tags/v0.1/D_TCPLightingGateway1.xml	(revision 3)
+++ /tags/v0.1/D_TCPLightingGateway1.xml	(revision 3)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<root xmlns="urn:schemas-upnp-org:device-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <device>
+    <deviceType>urn:schemas-pmcode-org:service:TCPLightingGateway:1</deviceType>
+    <staticJson>D_TCPLightingGateway1.json</staticJson>
+    <serviceList>
+      <service>
+        <serviceType>urn:schemas-pmcode-org:service:TCPLightingGateway:1</serviceType>
+        <serviceId>urn:pmcode-org:serviceId:TCPLightingGateway1</serviceId>
+        <SCPDURL>S_TCPLightingGateway1.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>
+      <implementationFile>I_TCPLighting1.xml</implementationFile>
+    </implementationList>
+  </device>
+</root>
Index: /tags/v0.1/D_TCPLighting1.xml
===================================================================
--- /tags/v0.1/D_TCPLighting1.xml	(revision 3)
+++ /tags/v0.1/D_TCPLighting1.xml	(revision 3)
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<root xmlns="urn:schemas-upnp-org:device-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <device>
+    <deviceType>urn:schemas-upnp-org:device:DimmableLight:1</deviceType>
+    <staticJson>D_DimmableLight1.json</staticJson>
+    <serviceList>
+      <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-upnp-org:service:Dimming:1</serviceType>
+        <serviceId>urn:upnp-org:serviceId:Dimming1</serviceId>
+        <SCPDURL>S_Dimming1.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>
+      <implementationFile>I_TCPLighting1.xml</implementationFile>
+    </implementationList>
+  </device>
+</root>
Index: /tags/v0.1/test.lua
===================================================================
--- /tags/v0.1/test.lua	(revision 3)
+++ /tags/v0.1/test.lua	(revision 3)
@@ -0,0 +1,27 @@
+local tcplighting = require("L_TCPLighting1")
+local json = require ("json")
+
+
+-- initialize gateway
+gateway = tcplighting_gateway_init("192.168.1.110")
+print (json.encode(gateway.devices))
+
+
+
+
+-- modify a light's intensity
+if (gateway.initialized) then
+    -- generate a random intensity
+	math.randomseed(os.time())
+    math.random(); math.random(); math.random()
+    local load_level_target = math.random(100)
+	--  call the gateway
+    tcplighting_set_load_level_target_by_name(gateway, "Front Entry Light", "Front Hall", load_level_target)
+    tcplighting_set_target_by_name(gateway, "Front Entry Light", "Front Hall", 1)
+	-- poll to get latest status
+    tcplighting_gateway_poll(gateway)
+    print (json.encode(gateway.devices))
+else
+    print ("--- ERROR: " .. gateway.error_text)
+end
+
Index: /tags/v0.1/I_TCPLighting1.xml
===================================================================
--- /tags/v0.1/I_TCPLighting1.xml	(revision 3)
+++ /tags/v0.1/I_TCPLighting1.xml	(revision 3)
@@ -0,0 +1,378 @@
+<?xml version="1.0"?>
+<implementation>
+  <functions>
+
+       -- ---------------------------------------------------------------------
+       -- Constants
+       -- ---------------------------------------------------------------------
+       local GATEWAY_DEVICE_TYPE = "urn:schemas-pmcode-org:service:TCPLightingGateway:1"
+       local GATEWAY_SERVICE_ID  = "urn:pmcode-org:serviceId:TCPLightingGateway1"
+       local HA_DEVICE_TYPE      = "urn:schemas-micasaverde-com:service:HaDevice:1"
+       local HA_SERVICE_ID       = "urn:micasaverde-com:serviceId:HaDevice1"
+       local DIMMER_DEVICE_TYPE  = "urn:schemas-upnp-org:device:DimmableLight:1"
+       local DIMMER_SERVICE_ID   = "urn:upnp-org:serviceId:Dimming1"
+       local SWITCH_DEVICE_TYPE  = "urn:schemas-upnp-org:device:SwitchPower:1"
+       local SWITCH_SERVICE_ID   = "urn:upnp-org:serviceId:SwitchPower1"
+       local LIGHT_DEVICE_FILE   = "D_TCPLighting1.xml"
+
+
+       -- ---------------------------------------------------------------------
+       -- table respresenting the gateway and its devices
+       -- ---------------------------------------------------------------------
+       local tcplighting_gateway = nil
+
+
+       -- ---------------------------------------------------------------------
+       -- Get a reference to the gateway (will init if necessary)
+       -- ---------------------------------------------------------------------
+	   local function get_gateway (gateway_ip)
+		  if not tcplighting_gateway then
+			 tcplighting_gateway = tcplighting_gateway_init (gateway_ip)
+			 if tcplighting_gateway.error_text then
+				luup.task(tcplighting_gateway.error_text, 2, "TCPLighting", -1)
+			 end
+		  end
+		  return tcplighting_gateway
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Returns true if the device has dimming capabilities
+       -- ---------------------------------------------------------------------
+       local function is_dimmer_switch (device)
+           return (device and device.capability and string.find(device.capability,"switch_multilevel"))
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Returns true if the device has on/off capabilities
+       -- ---------------------------------------------------------------------
+       local function is_binary_switch (device)
+           return (device and device.capability and string.find(device.capability,"switch_binary"))
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- See if we have a matching room number
+       -- ---------------------------------------------------------------------
+       local function room_number (input_room_name)
+          local room_number = 0
+          if input_room_name then
+              for i, room_name in ipairs(luup.rooms) do
+                  if room_name == input_room_name then
+                      room_number = i
+                      break
+                  end
+              end
+          end
+          return room_number
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Sets a LUUP device variable, but only if it has no current value
+       -- ---------------------------------------------------------------------
+       local function initialize_variable (service_id, variable_name, new_value, device_number)
+          local current_value = luup.variable_get (service_id, variable_name, device_number)
+          if (not current_value) or (current_value == "") then
+              luup.variable_set (service_id, variable_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Sets a LUUP device attribute, but only if it has no current value
+       -- ---------------------------------------------------------------------
+       local function initialize_attr (attr_name, new_value, device_number)
+          local current_value = luup.attr_get (attr_name, device_number)
+          if (not current_value) or (current_value == "") then
+              luup.attr_set (attr_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Updates a LUUP device variable, but only if its value has changed
+       -- ---------------------------------------------------------------------
+       local function update_variable (service_id, variable_name, new_value, device_number)
+          local current_value = luup.variable_get (service_id, variable_name, device_number)
+          if (not current_value) or (new_value ~= current_value) then
+              luup.variable_set (service_id, variable_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Updates a LUUP device attribute, but only if its value has changed
+       -- ---------------------------------------------------------------------
+       local function update_attr (attr_name, new_value, device_number)
+          local current_value = luup.attr_get (attr_name, device_number)
+          if (not current_value) or (new_value ~= current_value) then
+              luup.attr_set (attr_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Update a device to match info from gateway
+       -- ---------------------------------------------------------------------
+       local function update_device_settings (gateway, did, lul_device)
+
+           luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - start")
+
+           if not (gateway and did and lul_device) then
+              return
+           end
+
+           -- update the device
+
+           local device_number = tonumber(lul_device)
+           local device = gateway.devices[did]
+
+           if device and device.room and device.room.name then
+               luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting room_num")
+               update_attr ("room_num", tostring(room_number(device.room.name)), device_number)
+               update_attr ("room",     tostring(room_number(device.room.name)), device_number)
+           end
+
+           if device and is_binary_switch(device) then
+               luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting Status")
+		       update_variable (SWITCH_SERVICE_ID, "Status", device.state, device_number)
+		       update_variable (SWITCH_SERVICE_ID, "Target", device.state, device_number)
+           end
+
+           if device and is_dimmer_switch(device) then
+              luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting LoadLevelStatus")
+		      update_variable (DIMMER_SERVICE_ID, "LoadLevelStatus", device.level, device_number)
+		      update_variable (DIMMER_SERVICE_ID, "LoadLevelTarget", device.level, device_number)
+           end
+
+           luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - end")
+
+           return
+
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Update all of the children of the specified device
+       -- ---------------------------------------------------------------------
+       local function sync_child_devices (gateway, parent_lul_device)
+
+           luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - start")
+
+           if not (gateway and parent_lul_device) then
+              return
+           end
+
+           -- poll the gateway for most current device data
+           tcplighting_gateway_poll(gateway)
+
+
+           -- find matching child devices
+           local parent_device_number = tonumber (parent_lul_device)
+           for k, luup_device in pairs(luup.devices) do
+               luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - checking device " .. k .. " ".. luup_device.description .. " with parent " .. tostring(luup_device.device_num_parent))
+               if (luup_device.device_num_parent == parent_device_number) and (luup_device.id) then
+                    luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - updating child " .. k)
+                    update_device_settings (gateway, luup_device.id, k)
+               end
+           end
+
+           luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - end")
+
+           return
+
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Create child devices of gateway if necessary
+       -- ---------------------------------------------------------------------
+       local function create_child_devices (gateway, lul_device)
+
+           luup.log ("TCPLighting: create_child_devices - start")
+
+           if gateway and gateway.initialized then
+
+              luup.log ("TCPLighting: create_child_devices - gateway is initialized")
+
+              local child_devices = luup.chdev.start (lul_device)
+
+              for did,device in pairs(gateway.devices) do
+                  if is_dimmer_switch (device) then
+                     luup.log ("TCPLighting: create_child_devices - creating dimmer child")
+                     luup.chdev.append (lul_device, child_devices, device.did, device.name, DIMMER_DEVICE_TYPE, LIGHT_DEVICE_FILE,"","",false)
+                  elseif is_binary_switch (device) then
+                     luup.log ("TCPLighting: create_child_devices - creating switch child")
+                     luup.chdev.append (lul_device, child_devices, device.did, device.name, SWITCH_DEVICE_TYPE, LIGHT_DEVICE_FILE,"","",false)
+                  end
+              end
+
+              luup.chdev.sync (lul_device, child_devices)
+
+           end
+
+		   luup.log ("TCPLighting: create_child_devices - end")
+
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Schedule the next poll
+       -- ---------------------------------------------------------------------
+	   local function schedule_next_poll (lul_device)
+
+		   luup.log ("TCPLighting: schedule_next_poll - start")
+
+           local device_number = tonumber(lul_device)
+
+		   -- make sure the polling variables have values
+		   initialize_variable (HA_SERVICE_ID, "PollingEnabled", "true", device_number)
+		   initialize_variable (HA_SERVICE_ID, "PollMinDelay",   "60",   device_number)
+
+           -- get current polling settings (may be different from above if overriden by user)
+		   local polling_enabled  = luup.variable_get (HA_SERVICE_ID, "PollingEnabled", device_number)
+		   local polling_interval = luup.variable_get (HA_SERVICE_ID, "PollMinDelay",   device_number)
+
+		   -- make a delayed call to the synchronization functions
+		   if polling_enabled == "true" or polling_enabled == "1" then
+		      luup.call_timer("synchronize_gateway", 1, tonumber(polling_interval), "", lul_device)
+			  luup.log ("TCPLighting: schedule_next_poll - timer set")
+		   end
+
+		   luup.log ("TCPLighting: schedule_next_poll - end")
+
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Contact the gateway and initialize the gateway object
+       -- ---------------------------------------------------------------------
+	   function synchronize_gateway (lul_device)
+
+		   luup.log ("TCPLighting: synchronize_gateway - start")
+
+           local device_number = tonumber(lul_device)
+           local gateway_ip = luup.devices[device_number].ip
+
+           -- will create and populate a new gateway configuration object if necessary
+           local gateway = get_gateway (gateway_ip)
+
+           -- bail if there was an error
+		   if gateway.error_text then
+               update_variable (GATEWAY_SERVICE_ID, "ErrorText", gateway.error_text, device_number)
+			   return false
+		   else
+               update_variable (GATEWAY_SERVICE_ID, "ErrorText", "", device_number)
+           end
+
+           -- create and synchronize all chldren
+		   create_child_devices (gateway, lul_device)
+           sync_child_devices (gateway, lul_device)
+
+		   -- set up polling so that changes made externally to the plugin show up in the UI
+		   schedule_next_poll (lul_device)
+
+
+		   luup.log ("TCPLighting: synchronize_gateway - end")
+
+           return true
+
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Set the dimming level on a light
+       -- ---------------------------------------------------------------------
+       local function set_load_level_target (lul_device, lul_settings)
+	       local device_number = tonumber(lul_device)
+           local gateway_ip = luup.devices[device_number].ip
+           local did = luup.devices[device_number].id
+		   local gateway = get_gateway (gateway_ip)
+		   if gateway.initialized and did then
+               tcplighting_set_load_level_target (gateway, did, tonumber(lul_settings.newLoadlevelTarget))
+               tcplighting_gateway_poll (gateway)
+			   update_device_settings (gateway, did, lul_device)
+           end
+           return true
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Flips switch on/off
+       -- ---------------------------------------------------------------------
+       local function set_target (lul_device, lul_settings)
+	       local device_number = tonumber(lul_device)
+           local gateway_ip = luup.devices[device_number].ip
+           local did = luup.devices[device_number].id
+		   local gateway = get_gateway (gateway_ip)
+		   if gateway.initialized and did then
+               tcplighting_set_target (gateway, did, tonumber(lul_settings.newTargetValue))
+               tcplighting_gateway_poll (gateway)
+			   update_device_settings (gateway, did, lul_device)
+           end
+           return true
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Plugin startup
+       -- Will initialize the gateway, which in turn creates child devices
+       -- for each light as necessary
+       -- ---------------------------------------------------------------------
+      function tcplighting_plugin_startup (lul_device)
+
+		  luup.log ("TCPLighting: tcplighting_plugin_startup - start")
+
+	      local device_number = tonumber(lul_device)
+          local device_type = luup.devices[device_number].device_type
+
+	      if device_type == GATEWAY_DEVICE_TYPE then
+             luup.log ("TCPLighting: tcplighting_plugin_startup - is gateway")
+		     synchronize_gateway (lul_device)
+          else
+             luup.log ("TCPLighting: tcplighting_plugin_startup - not gateway")
+		  end
+
+		  luup.log ("TCPLighting: tcplighting_plugin_startup - end")
+
+	  end
+
+
+  </functions>
+
+  <startup>tcplighting_plugin_startup</startup>
+
+  <files>L_TCPLighting1.lua</files>
+
+  <actionList>
+
+    <action>
+      <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId>
+      <name>SetTarget</name>
+      <run>return set_target (lul_device, lul_settings)</run>
+    </action>
+
+    <action>
+      <serviceId>urn:upnp-org:serviceId:Dimming1</serviceId>
+      <name>SetLoadLevelTarget</name>
+      <run>return set_load_level_target (lul_device, lul_settings)</run>
+    </action>
+
+    <action>
+      <serviceId>urn:pmcode-org:serviceId:TCPLightingGateway1</serviceId>
+      <name>Synchronize</name>
+      <run>return synchronize_gateway (lul_device)</run>
+    </action>
+
+	<action>
+      <serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId>
+      <name>Poll</name>
+      <run>return synchronize_gateway (lul_device)</run>
+    </action>
+
+   </actionList>
+
+</implementation>
+
Index: /tags/v0.1/L_TCPLighting1.lua
===================================================================
--- /tags/v0.1/L_TCPLighting1.lua	(revision 3)
+++ /tags/v0.1/L_TCPLighting1.lua	(revision 3)
@@ -0,0 +1,238 @@
+-- ----------------------------------------------------------------------------
+-- Implements urn:upnp-org:serviceId:SwitchPower1.SetTarget
+-- ----------------------------------------------------------------------------
+ function tcplighting_set_target (gateway, did, target_value)
+
+    local http = require("socket.http")
+
+    http.TIMEOUT = gateway.HTTP_TIMEOUT
+
+    return http.request("http://" .. gateway.devices[did].gateway_ip
+                        .. "/gwr/gop.php",
+                        "cmd=DeviceSendCommand&data="
+                        .. "<gip>"
+                        .. "<version>1</version>"
+                        .. "<token>1234567890</token>"
+                        .. "<did>" .. did .. "</did>"
+                        .. "<value>" .. target_value .. "</value>"
+                        .. "</gip>"
+                        .. "&fmt=xml")
+end
+
+-- ----------------------------------------------------------------------------
+-- Implements urn:upnp-org:serviceId:Dimming1.SetLoadLevelTarget
+-- ----------------------------------------------------------------------------
+ function tcplighting_set_load_level_target (gateway, did, load_percent)
+
+    local http = require("socket.http")
+
+    http.TIMEOUT = gateway.HTTP_TIMEOUT
+
+	-- make sure light is on/off to match request
+	if load_percent > 0 then
+	    tcplighting_set_target (gateway, did, 1)
+	else
+	    tcplighting_set_target (gateway, did, 0)
+	end
+
+	-- change the dimming level
+    return http.request("http://" .. gateway.devices[did].gateway_ip
+                        .. "/gwr/gop.php",
+                        "cmd=DeviceSendCommand&data="
+                        .. "<gip>"
+                        .. "<version>1</version>"
+                        .. "<token>1234567890</token>"
+                        .. "<did>" .. did .. "</did>"
+                        .. "<value>" .. load_percent .. "</value>"
+                        .. "<type>level</type>"
+                        .. "</gip>"
+                        .. "&fmt=xml")
+end
+
+
+-- ----------------------------------------------------------------------------
+-- Loads the gateway configuration
+-- ----------------------------------------------------------------------------
+
+ function tcplighting_gateway_init (gateway_ip)
+
+ 	-- create an empty gateway object
+	local gateway = {}
+    gateway.initialized  = false
+    gateway.error_text   = "TCP Lighting Gateway not yet initialized"  -- error text for last failed operation
+	gateway.gateway_ip   = gateway_ip
+    gateway.devices      = {}    -- a cache of device info indexed by unique did
+    gateway.HTTP_TIMEOUT = 5   -- 5 seconds should be fine on a local network
+
+	-- Make sure a gateway ip was specified
+	if not gateway_ip or string.len(gateway_ip) == 0 then
+	   gateway.error_text = "No gateway IP address specified"
+	   return gateway
+	end
+
+	-- Get the gateway's configuration data
+    tcplighting_gateway_poll (gateway)
+
+	return gateway
+
+end
+
+-- ----------------------------------------------------------------------------
+-- Get current values from the gateway
+-- ----------------------------------------------------------------------------
+
+ function tcplighting_gateway_poll (gateway)
+
+   	-- Get the gateway's configuration data
+    local result, status = tcplighting_get_gateway_config (gateway)
+
+	-- Check the HTTP status
+    if status ~= 200 then
+	   gateway.error_text = "HTTP gateway query request to " .. gateway.gateway_ip .. " failed"
+	   if status then gateway.error_text = gateway.error_text .. " - " .. status     end
+	   if result then gateway.error_text = gateway.error_text .. " - " .. result     end
+	   return
+	end
+
+	-- Make sure something came back
+	if not result then
+	   gateway.error_text = "HTTP gateway query request to " .. gateway.gateway_ip .. " did not return any data"
+	   return
+	end
+
+    -- Only parse if the HTTP request was successful
+    tcplighting_parse_gateway_config(gateway, result)
+    return
+
+end
+
+-- ----------------------------------------------------------------------------
+-- Queries a Connected by TCP Gateway to determine which lights are available
+-- ----------------------------------------------------------------------------
+ function tcplighting_get_gateway_config (gateway)
+
+    local http = require("socket.http")
+
+    http.TIMEOUT = gateway.HTTP_TIMEOUT
+
+    return http.request("http://" .. gateway.gateway_ip
+                        .. "/gwr/gop.php",
+                        "cmd=GWRBatch&data="
+                        .. "<gwrcmds>"
+                        .. "<gwrcmd>"
+                        .. "<gcmd>RoomGetCarousel</gcmd>"
+                        .. "<gdata>"
+                        .. "<gip>"
+                        .. "<version>1</version>"
+                        .. "<token>1234567890</token>"
+                        .. "<fields>name,image,imageurl,control,power,product,class,realtype,status</fields>"
+                        .. "</gip>"
+                        .. "</gdata>"
+                        .. "</gwrcmd>"
+                        .. "</gwrcmds>"
+                        .. "&fmt=xml")
+end
+
+
+-- ----------------------------------------------------------------------------
+-- Parse the gateway configuration
+-- ----------------------------------------------------------------------------
+
+ function tcplighting_parse_gateway_config (gateway, config_xml)
+
+	local lxp = require("lxp")
+	local json = require ("json")
+
+	-- Local collection devices - will be added to master table after parsing
+	local new_devices = {}
+
+	-- enumerate the XML elements that we want to load into our tables
+	local room_elements_of_interest = "|rid|name|desc|"
+	local device_elements_of_interest = "|did|name|desc|state|level|type|rangemin|rangemax|power|poweravg|energy|manufacturer|prodbrand|prodmodel|prodtype|capability|"
+
+	-- used to keep track of the current context during the parsing process
+    local current_room_object = nil
+	local current_device_object = nil
+	local current_element_name = nil
+
+	-- XML parsing handler for the start of an element
+	local function start_element_handler (parser, name)
+		current_element_name = name
+	    if name == "room" then
+			current_room_object = {}
+		elseif name == "device" then
+			current_device_object = {}
+			current_device_object["gateway_ip"] = gateway.gateway_ip
+			current_device_object["room"] = current_room_object
+        end
+	end
+
+	-- XML parsing handler for the end of an element
+	local function end_element_handler (parser, name)
+		current_element_name = name
+	    if name == "room" then
+			current_room_object = nil
+		elseif name == "device" then
+		     new_devices[#new_devices+1] = current_device_object
+			current_device_object = nil
+        end
+	end
+
+	-- XML parsing handler for the text of an element
+	local function character_handler (parser, value)
+		if current_device_object and string.find(device_elements_of_interest,"|"..current_element_name.."|") then
+		    current_device_object[current_element_name] = value
+		elseif current_room_object and (not current_device_object) and string.find(room_elements_of_interest,"|"..current_element_name.."|") then
+			current_room_object[current_element_name] = value
+        end
+	end
+
+	-- Create a parser
+	local callbacks = {StartElement = start_element_handler, EndElement = end_element_handler, CharacterData = character_handler}
+	local parser = lxp.new(callbacks)
+
+	-- Parse the XML
+	parser:parse(config_xml)
+	parser:parse() -- finishes the document
+	parser:close()
+
+	-- Save the devices, uniquely indexed by did
+	if #new_devices > 0 then
+	    for i,device in ipairs(new_devices) do
+	        gateway.devices[device.did] = device
+			-- tweak for interpretation of load level for dimmers - always set to zero if device is off
+			if device.state == "0" then
+			   device.level = "0"
+			end
+        end
+		gateway.initialized = true
+		gateway.error_text = nil
+	else
+		gateway.error_text = "No devices found at gateway " .. gateway.gateway_ip .. " while parsing " .. config_xml
+	end
+
+	return
+
+end
+
+-- ----------------------------------------------------------------------------
+-- Helper functions for testing - call devices by name/room
+-- ----------------------------------------------------------------------------
+
+function tcplighting_get_did (gateway, name, roomname)
+   local did = nil
+   for key,device in pairs(gateway.devices) do
+      if device.name == name and device.room.name == roomname then
+         did = device.did
+      end
+   end
+   return did
+end
+
+function tcplighting_set_target_by_name  (gateway, name, roomname, target_value)
+    return tcplighting_set_target(gateway, tcplighting_get_did (gateway, name, roomname), target_value)
+end
+
+function tcplighting_set_load_level_target_by_name (gateway, name, roomname, load_percent)
+    return tcplighting_set_load_level_target(gateway, tcplighting_get_did (gateway, name, roomname), load_percent)
+end
Index: /tags/v0.1/D_TCPLightingGateway1.json
===================================================================
--- /tags/v0.1/D_TCPLightingGateway1.json	(revision 3)
+++ /tags/v0.1/D_TCPLightingGateway1.json	(revision 3)
@@ -0,0 +1,95 @@
+{
+    "flashicon":      "icons/generic_sensor.swf",
+    "imgIconBody":     "",
+    "imgIconDimmable": "",
+    "imgIconTurnable": "",
+    "imgIconMin":      "",
+    "imgIconMax":      "",
+    "halloIconsDir":   "pics/hallo",
+    "inScene":         "0",
+    "DisplayStatus":   {},
+    "doc_url":
+       {
+       "doc_language": 1,
+	   "doc_manual":   1,
+       "doc_version":  1,
+       "doc_platform": 0,
+       "doc_page":     "lighting_devices"
+       },
+    "Tabs":
+	   [
+
+       {
+       "Label":    {"lang_tag": "tcp_lighting_gateway", "text": "Gateway"},
+       "Position": "0",
+       "TabType":  "flash",
+	   "SceneGroup":
+	        [
+		    {
+			"id": "1",
+			"top": "1",
+			"left": "0",
+			"x": "1",
+			"y": "1"
+		    },
+		    {
+			"id": "2",
+			"top": "2",
+			"left": "0",
+			"x": "1",
+			"y": "2"
+		    }
+		    ],
+		"ControlGroup": [
+			{
+			"id": "1",
+			"scenegroup": "1",
+			"isSingle": "1"
+			},
+			{
+			"id": "2",
+			"scenegroup": "2",
+			"type": "info"
+			}
+		],
+       "Control":
+		    [
+            {
+            "ControlType": "label",
+            "Label":       {"lang_tag": "synchronize_desc","text": "Sync to the gateway and configure lights - Gateway ip must be specified in Advanced tab"},
+            "Display":     {"Top": 20,"Left": 50,"Width": 200,"Height": 20}
+            },
+            {
+            "ControlGroup": "1",
+            "ControlType":  "button",
+            "Label":       {"lang_tag": "synchronize_command","text": "Sync"},
+			"Display":     {"Top": 37,"Left": 50, "Width": 100, "Height": 20 },
+            "Command":     {"Service": "urn:pmcode-org:serviceId:TCPLightingGateway1", "Action": "Synchronize", "Parameters": []}
+			},
+            {
+            "ControlType": "label",
+            "Label":       {"lang_tag": "error_text_label","text": "Gateway Errors:"},
+			"Display":     {"Top": 80,"Left": 50,"Width": 200, "Height": 20}
+			},
+            {
+            "ControlGroup": "2",
+            "ControlType": "variable",
+            "Display":     {"Top": 95, "Left": 70, "Width": 200, "Height": 20,
+			                "Service": "urn:pmcode-org:serviceId:TCPLightingGateway1", "Variable": "ErrorText"}
+			}
+            ]
+        },
+
+        {
+        "Label":      {"lang_tag": "advanced","text": "Advanced"},
+        "Position":   "1",
+        "TabType":    "javascript",
+        "ScriptName": "shared.js",
+        "Function":   "advanced_device"
+        }
+    ],
+    "eventList":   {},
+    "eventList2":  [],
+    "DeviceType":  "urn:schemas-pmcode-org:device:TCPLightingGateway:1",
+    "device_type": "urn:schemas-pmcode-org:device:TCPLightingGateway:1"
+}
Index: /trunk/S_TCPLightingGateway1.xml
===================================================================
--- /trunk/S_TCPLightingGateway1.xml	(revision 3)
+++ /trunk/S_TCPLightingGateway1.xml	(revision 3)
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <serviceStateTable>
+    <stateVariable sendEvents="yes">
+      <name>Initialized</name>
+      <dataType>boolean</dataType>
+      <defaultValue>0</defaultValue>
+    </stateVariable>
+    <stateVariable sendEvents="no">
+      <name>ErrorText</name>
+      <dataType>string</dataType>
+    </stateVariable>
+  </serviceStateTable>
+  <actionList>
+    <action>
+      <name>Synchronize</name>
+    </action>
+  </actionList>
+</scpd>
Index: /trunk/D_TCPLightingGateway1.xml
===================================================================
--- /trunk/D_TCPLightingGateway1.xml	(revision 3)
+++ /trunk/D_TCPLightingGateway1.xml	(revision 3)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<root xmlns="urn:schemas-upnp-org:device-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <device>
+    <deviceType>urn:schemas-pmcode-org:service:TCPLightingGateway:1</deviceType>
+    <staticJson>D_TCPLightingGateway1.json</staticJson>
+    <serviceList>
+      <service>
+        <serviceType>urn:schemas-pmcode-org:service:TCPLightingGateway:1</serviceType>
+        <serviceId>urn:pmcode-org:serviceId:TCPLightingGateway1</serviceId>
+        <SCPDURL>S_TCPLightingGateway1.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>
+      <implementationFile>I_TCPLighting1.xml</implementationFile>
+    </implementationList>
+  </device>
+</root>
Index: /trunk/D_TCPLighting1.xml
===================================================================
--- /trunk/D_TCPLighting1.xml	(revision 3)
+++ /trunk/D_TCPLighting1.xml	(revision 3)
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<root xmlns="urn:schemas-upnp-org:device-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <device>
+    <deviceType>urn:schemas-upnp-org:device:DimmableLight:1</deviceType>
+    <staticJson>D_DimmableLight1.json</staticJson>
+    <serviceList>
+      <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-upnp-org:service:Dimming:1</serviceType>
+        <serviceId>urn:upnp-org:serviceId:Dimming1</serviceId>
+        <SCPDURL>S_Dimming1.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>
+      <implementationFile>I_TCPLighting1.xml</implementationFile>
+    </implementationList>
+  </device>
+</root>
Index: /trunk/test.lua
===================================================================
--- /trunk/test.lua	(revision 3)
+++ /trunk/test.lua	(revision 3)
@@ -0,0 +1,27 @@
+local tcplighting = require("L_TCPLighting1")
+local json = require ("json")
+
+
+-- initialize gateway
+gateway = tcplighting_gateway_init("192.168.1.110")
+print (json.encode(gateway.devices))
+
+
+
+
+-- modify a light's intensity
+if (gateway.initialized) then
+    -- generate a random intensity
+	math.randomseed(os.time())
+    math.random(); math.random(); math.random()
+    local load_level_target = math.random(100)
+	--  call the gateway
+    tcplighting_set_load_level_target_by_name(gateway, "Front Entry Light", "Front Hall", load_level_target)
+    tcplighting_set_target_by_name(gateway, "Front Entry Light", "Front Hall", 1)
+	-- poll to get latest status
+    tcplighting_gateway_poll(gateway)
+    print (json.encode(gateway.devices))
+else
+    print ("--- ERROR: " .. gateway.error_text)
+end
+
Index: /trunk/I_TCPLighting1.xml
===================================================================
--- /trunk/I_TCPLighting1.xml	(revision 3)
+++ /trunk/I_TCPLighting1.xml	(revision 3)
@@ -0,0 +1,378 @@
+<?xml version="1.0"?>
+<implementation>
+  <functions>
+
+       -- ---------------------------------------------------------------------
+       -- Constants
+       -- ---------------------------------------------------------------------
+       local GATEWAY_DEVICE_TYPE = "urn:schemas-pmcode-org:service:TCPLightingGateway:1"
+       local GATEWAY_SERVICE_ID  = "urn:pmcode-org:serviceId:TCPLightingGateway1"
+       local HA_DEVICE_TYPE      = "urn:schemas-micasaverde-com:service:HaDevice:1"
+       local HA_SERVICE_ID       = "urn:micasaverde-com:serviceId:HaDevice1"
+       local DIMMER_DEVICE_TYPE  = "urn:schemas-upnp-org:device:DimmableLight:1"
+       local DIMMER_SERVICE_ID   = "urn:upnp-org:serviceId:Dimming1"
+       local SWITCH_DEVICE_TYPE  = "urn:schemas-upnp-org:device:SwitchPower:1"
+       local SWITCH_SERVICE_ID   = "urn:upnp-org:serviceId:SwitchPower1"
+       local LIGHT_DEVICE_FILE   = "D_TCPLighting1.xml"
+
+
+       -- ---------------------------------------------------------------------
+       -- table respresenting the gateway and its devices
+       -- ---------------------------------------------------------------------
+       local tcplighting_gateway = nil
+
+
+       -- ---------------------------------------------------------------------
+       -- Get a reference to the gateway (will init if necessary)
+       -- ---------------------------------------------------------------------
+	   local function get_gateway (gateway_ip)
+		  if not tcplighting_gateway then
+			 tcplighting_gateway = tcplighting_gateway_init (gateway_ip)
+			 if tcplighting_gateway.error_text then
+				luup.task(tcplighting_gateway.error_text, 2, "TCPLighting", -1)
+			 end
+		  end
+		  return tcplighting_gateway
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Returns true if the device has dimming capabilities
+       -- ---------------------------------------------------------------------
+       local function is_dimmer_switch (device)
+           return (device and device.capability and string.find(device.capability,"switch_multilevel"))
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Returns true if the device has on/off capabilities
+       -- ---------------------------------------------------------------------
+       local function is_binary_switch (device)
+           return (device and device.capability and string.find(device.capability,"switch_binary"))
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- See if we have a matching room number
+       -- ---------------------------------------------------------------------
+       local function room_number (input_room_name)
+          local room_number = 0
+          if input_room_name then
+              for i, room_name in ipairs(luup.rooms) do
+                  if room_name == input_room_name then
+                      room_number = i
+                      break
+                  end
+              end
+          end
+          return room_number
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Sets a LUUP device variable, but only if it has no current value
+       -- ---------------------------------------------------------------------
+       local function initialize_variable (service_id, variable_name, new_value, device_number)
+          local current_value = luup.variable_get (service_id, variable_name, device_number)
+          if (not current_value) or (current_value == "") then
+              luup.variable_set (service_id, variable_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Sets a LUUP device attribute, but only if it has no current value
+       -- ---------------------------------------------------------------------
+       local function initialize_attr (attr_name, new_value, device_number)
+          local current_value = luup.attr_get (attr_name, device_number)
+          if (not current_value) or (current_value == "") then
+              luup.attr_set (attr_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Updates a LUUP device variable, but only if its value has changed
+       -- ---------------------------------------------------------------------
+       local function update_variable (service_id, variable_name, new_value, device_number)
+          local current_value = luup.variable_get (service_id, variable_name, device_number)
+          if (not current_value) or (new_value ~= current_value) then
+              luup.variable_set (service_id, variable_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Updates a LUUP device attribute, but only if its value has changed
+       -- ---------------------------------------------------------------------
+       local function update_attr (attr_name, new_value, device_number)
+          local current_value = luup.attr_get (attr_name, device_number)
+          if (not current_value) or (new_value ~= current_value) then
+              luup.attr_set (attr_name, new_value, device_number)
+          end
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Update a device to match info from gateway
+       -- ---------------------------------------------------------------------
+       local function update_device_settings (gateway, did, lul_device)
+
+           luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - start")
+
+           if not (gateway and did and lul_device) then
+              return
+           end
+
+           -- update the device
+
+           local device_number = tonumber(lul_device)
+           local device = gateway.devices[did]
+
+           if device and device.room and device.room.name then
+               luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting room_num")
+               update_attr ("room_num", tostring(room_number(device.room.name)), device_number)
+               update_attr ("room",     tostring(room_number(device.room.name)), device_number)
+           end
+
+           if device and is_binary_switch(device) then
+               luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting Status")
+		       update_variable (SWITCH_SERVICE_ID, "Status", device.state, device_number)
+		       update_variable (SWITCH_SERVICE_ID, "Target", device.state, device_number)
+           end
+
+           if device and is_dimmer_switch(device) then
+              luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting LoadLevelStatus")
+		      update_variable (DIMMER_SERVICE_ID, "LoadLevelStatus", device.level, device_number)
+		      update_variable (DIMMER_SERVICE_ID, "LoadLevelTarget", device.level, device_number)
+           end
+
+           luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - end")
+
+           return
+
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Update all of the children of the specified device
+       -- ---------------------------------------------------------------------
+       local function sync_child_devices (gateway, parent_lul_device)
+
+           luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - start")
+
+           if not (gateway and parent_lul_device) then
+              return
+           end
+
+           -- poll the gateway for most current device data
+           tcplighting_gateway_poll(gateway)
+
+
+           -- find matching child devices
+           local parent_device_number = tonumber (parent_lul_device)
+           for k, luup_device in pairs(luup.devices) do
+               luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - checking device " .. k .. " ".. luup_device.description .. " with parent " .. tostring(luup_device.device_num_parent))
+               if (luup_device.device_num_parent == parent_device_number) and (luup_device.id) then
+                    luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - updating child " .. k)
+                    update_device_settings (gateway, luup_device.id, k)
+               end
+           end
+
+           luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - end")
+
+           return
+
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Create child devices of gateway if necessary
+       -- ---------------------------------------------------------------------
+       local function create_child_devices (gateway, lul_device)
+
+           luup.log ("TCPLighting: create_child_devices - start")
+
+           if gateway and gateway.initialized then
+
+              luup.log ("TCPLighting: create_child_devices - gateway is initialized")
+
+              local child_devices = luup.chdev.start (lul_device)
+
+              for did,device in pairs(gateway.devices) do
+                  if is_dimmer_switch (device) then
+                     luup.log ("TCPLighting: create_child_devices - creating dimmer child")
+                     luup.chdev.append (lul_device, child_devices, device.did, device.name, DIMMER_DEVICE_TYPE, LIGHT_DEVICE_FILE,"","",false)
+                  elseif is_binary_switch (device) then
+                     luup.log ("TCPLighting: create_child_devices - creating switch child")
+                     luup.chdev.append (lul_device, child_devices, device.did, device.name, SWITCH_DEVICE_TYPE, LIGHT_DEVICE_FILE,"","",false)
+                  end
+              end
+
+              luup.chdev.sync (lul_device, child_devices)
+
+           end
+
+		   luup.log ("TCPLighting: create_child_devices - end")
+
+       end
+
+
+       -- ---------------------------------------------------------------------
+       -- Schedule the next poll
+       -- ---------------------------------------------------------------------
+	   local function schedule_next_poll (lul_device)
+
+		   luup.log ("TCPLighting: schedule_next_poll - start")
+
+           local device_number = tonumber(lul_device)
+
+		   -- make sure the polling variables have values
+		   initialize_variable (HA_SERVICE_ID, "PollingEnabled", "true", device_number)
+		   initialize_variable (HA_SERVICE_ID, "PollMinDelay",   "60",   device_number)
+
+           -- get current polling settings (may be different from above if overriden by user)
+		   local polling_enabled  = luup.variable_get (HA_SERVICE_ID, "PollingEnabled", device_number)
+		   local polling_interval = luup.variable_get (HA_SERVICE_ID, "PollMinDelay",   device_number)
+
+		   -- make a delayed call to the synchronization functions
+		   if polling_enabled == "true" or polling_enabled == "1" then
+		      luup.call_timer("synchronize_gateway", 1, tonumber(polling_interval), "", lul_device)
+			  luup.log ("TCPLighting: schedule_next_poll - timer set")
+		   end
+
+		   luup.log ("TCPLighting: schedule_next_poll - end")
+
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Contact the gateway and initialize the gateway object
+       -- ---------------------------------------------------------------------
+	   function synchronize_gateway (lul_device)
+
+		   luup.log ("TCPLighting: synchronize_gateway - start")
+
+           local device_number = tonumber(lul_device)
+           local gateway_ip = luup.devices[device_number].ip
+
+           -- will create and populate a new gateway configuration object if necessary
+           local gateway = get_gateway (gateway_ip)
+
+           -- bail if there was an error
+		   if gateway.error_text then
+               update_variable (GATEWAY_SERVICE_ID, "ErrorText", gateway.error_text, device_number)
+			   return false
+		   else
+               update_variable (GATEWAY_SERVICE_ID, "ErrorText", "", device_number)
+           end
+
+           -- create and synchronize all chldren
+		   create_child_devices (gateway, lul_device)
+           sync_child_devices (gateway, lul_device)
+
+		   -- set up polling so that changes made externally to the plugin show up in the UI
+		   schedule_next_poll (lul_device)
+
+
+		   luup.log ("TCPLighting: synchronize_gateway - end")
+
+           return true
+
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Set the dimming level on a light
+       -- ---------------------------------------------------------------------
+       local function set_load_level_target (lul_device, lul_settings)
+	       local device_number = tonumber(lul_device)
+           local gateway_ip = luup.devices[device_number].ip
+           local did = luup.devices[device_number].id
+		   local gateway = get_gateway (gateway_ip)
+		   if gateway.initialized and did then
+               tcplighting_set_load_level_target (gateway, did, tonumber(lul_settings.newLoadlevelTarget))
+               tcplighting_gateway_poll (gateway)
+			   update_device_settings (gateway, did, lul_device)
+           end
+           return true
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Flips switch on/off
+       -- ---------------------------------------------------------------------
+       local function set_target (lul_device, lul_settings)
+	       local device_number = tonumber(lul_device)
+           local gateway_ip = luup.devices[device_number].ip
+           local did = luup.devices[device_number].id
+		   local gateway = get_gateway (gateway_ip)
+		   if gateway.initialized and did then
+               tcplighting_set_target (gateway, did, tonumber(lul_settings.newTargetValue))
+               tcplighting_gateway_poll (gateway)
+			   update_device_settings (gateway, did, lul_device)
+           end
+           return true
+	   end
+
+
+       -- ---------------------------------------------------------------------
+       -- Plugin startup
+       -- Will initialize the gateway, which in turn creates child devices
+       -- for each light as necessary
+       -- ---------------------------------------------------------------------
+      function tcplighting_plugin_startup (lul_device)
+
+		  luup.log ("TCPLighting: tcplighting_plugin_startup - start")
+
+	      local device_number = tonumber(lul_device)
+          local device_type = luup.devices[device_number].device_type
+
+	      if device_type == GATEWAY_DEVICE_TYPE then
+             luup.log ("TCPLighting: tcplighting_plugin_startup - is gateway")
+		     synchronize_gateway (lul_device)
+          else
+             luup.log ("TCPLighting: tcplighting_plugin_startup - not gateway")
+		  end
+
+		  luup.log ("TCPLighting: tcplighting_plugin_startup - end")
+
+	  end
+
+
+  </functions>
+
+  <startup>tcplighting_plugin_startup</startup>
+
+  <files>L_TCPLighting1.lua</files>
+
+  <actionList>
+
+    <action>
+      <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId>
+      <name>SetTarget</name>
+      <run>return set_target (lul_device, lul_settings)</run>
+    </action>
+
+    <action>
+      <serviceId>urn:upnp-org:serviceId:Dimming1</serviceId>
+      <name>SetLoadLevelTarget</name>
+      <run>return set_load_level_target (lul_device, lul_settings)</run>
+    </action>
+
+    <action>
+      <serviceId>urn:pmcode-org:serviceId:TCPLightingGateway1</serviceId>
+      <name>Synchronize</name>
+      <run>return synchronize_gateway (lul_device)</run>
+    </action>
+
+	<action>
+      <serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId>
+      <name>Poll</name>
+      <run>return synchronize_gateway (lul_device)</run>
+    </action>
+
+   </actionList>
+
+</implementation>
+
Index: /trunk/L_TCPLighting1.lua
===================================================================
--- /trunk/L_TCPLighting1.lua	(revision 3)
+++ /trunk/L_TCPLighting1.lua	(revision 3)
@@ -0,0 +1,238 @@
+-- ----------------------------------------------------------------------------
+-- Implements urn:upnp-org:serviceId:SwitchPower1.SetTarget
+-- ----------------------------------------------------------------------------
+ function tcplighting_set_target (gateway, did, target_value)
+
+    local http = require("socket.http")
+
+    http.TIMEOUT = gateway.HTTP_TIMEOUT
+
+    return http.request("http://" .. gateway.devices[did].gateway_ip
+                        .. "/gwr/gop.php",
+                        "cmd=DeviceSendCommand&data="
+                        .. "<gip>"
+                        .. "<version>1</version>"
+                        .. "<token>1234567890</token>"
+                        .. "<did>" .. did .. "</did>"
+                        .. "<value>" .. target_value .. "</value>"
+                        .. "</gip>"
+                        .. "&fmt=xml")
+end
+
+-- ----------------------------------------------------------------------------
+-- Implements urn:upnp-org:serviceId:Dimming1.SetLoadLevelTarget
+-- ----------------------------------------------------------------------------
+ function tcplighting_set_load_level_target (gateway, did, load_percent)
+
+    local http = require("socket.http")
+
+    http.TIMEOUT = gateway.HTTP_TIMEOUT
+
+	-- make sure light is on/off to match request
+	if load_percent > 0 then
+	    tcplighting_set_target (gateway, did, 1)
+	else
+	    tcplighting_set_target (gateway, did, 0)
+	end
+
+	-- change the dimming level
+    return http.request("http://" .. gateway.devices[did].gateway_ip
+                        .. "/gwr/gop.php",
+                        "cmd=DeviceSendCommand&data="
+                        .. "<gip>"
+                        .. "<version>1</version>"
+                        .. "<token>1234567890</token>"
+                        .. "<did>" .. did .. "</did>"
+                        .. "<value>" .. load_percent .. "</value>"
+                        .. "<type>level</type>"
+                        .. "</gip>"
+                        .. "&fmt=xml")
+end
+
+
+-- ----------------------------------------------------------------------------
+-- Loads the gateway configuration
+-- ----------------------------------------------------------------------------
+
+ function tcplighting_gateway_init (gateway_ip)
+
+ 	-- create an empty gateway object
+	local gateway = {}
+    gateway.initialized  = false
+    gateway.error_text   = "TCP Lighting Gateway not yet initialized"  -- error text for last failed operation
+	gateway.gateway_ip   = gateway_ip
+    gateway.devices      = {}    -- a cache of device info indexed by unique did
+    gateway.HTTP_TIMEOUT = 5   -- 5 seconds should be fine on a local network
+
+	-- Make sure a gateway ip was specified
+	if not gateway_ip or string.len(gateway_ip) == 0 then
+	   gateway.error_text = "No gateway IP address specified"
+	   return gateway
+	end
+
+	-- Get the gateway's configuration data
+    tcplighting_gateway_poll (gateway)
+
+	return gateway
+
+end
+
+-- ----------------------------------------------------------------------------
+-- Get current values from the gateway
+-- ----------------------------------------------------------------------------
+
+ function tcplighting_gateway_poll (gateway)
+
+   	-- Get the gateway's configuration data
+    local result, status = tcplighting_get_gateway_config (gateway)
+
+	-- Check the HTTP status
+    if status ~= 200 then
+	   gateway.error_text = "HTTP gateway query request to " .. gateway.gateway_ip .. " failed"
+	   if status then gateway.error_text = gateway.error_text .. " - " .. status     end
+	   if result then gateway.error_text = gateway.error_text .. " - " .. result     end
+	   return
+	end
+
+	-- Make sure something came back
+	if not result then
+	   gateway.error_text = "HTTP gateway query request to " .. gateway.gateway_ip .. " did not return any data"
+	   return
+	end
+
+    -- Only parse if the HTTP request was successful
+    tcplighting_parse_gateway_config(gateway, result)
+    return
+
+end
+
+-- ----------------------------------------------------------------------------
+-- Queries a Connected by TCP Gateway to determine which lights are available
+-- ----------------------------------------------------------------------------
+ function tcplighting_get_gateway_config (gateway)
+
+    local http = require("socket.http")
+
+    http.TIMEOUT = gateway.HTTP_TIMEOUT
+
+    return http.request("http://" .. gateway.gateway_ip
+                        .. "/gwr/gop.php",
+                        "cmd=GWRBatch&data="
+                        .. "<gwrcmds>"
+                        .. "<gwrcmd>"
+                        .. "<gcmd>RoomGetCarousel</gcmd>"
+                        .. "<gdata>"
+                        .. "<gip>"
+                        .. "<version>1</version>"
+                        .. "<token>1234567890</token>"
+                        .. "<fields>name,image,imageurl,control,power,product,class,realtype,status</fields>"
+                        .. "</gip>"
+                        .. "</gdata>"
+                        .. "</gwrcmd>"
+                        .. "</gwrcmds>"
+                        .. "&fmt=xml")
+end
+
+
+-- ----------------------------------------------------------------------------
+-- Parse the gateway configuration
+-- ----------------------------------------------------------------------------
+
+ function tcplighting_parse_gateway_config (gateway, config_xml)
+
+	local lxp = require("lxp")
+	local json = require ("json")
+
+	-- Local collection devices - will be added to master table after parsing
+	local new_devices = {}
+
+	-- enumerate the XML elements that we want to load into our tables
+	local room_elements_of_interest = "|rid|name|desc|"
+	local device_elements_of_interest = "|did|name|desc|state|level|type|rangemin|rangemax|power|poweravg|energy|manufacturer|prodbrand|prodmodel|prodtype|capability|"
+
+	-- used to keep track of the current context during the parsing process
+    local current_room_object = nil
+	local current_device_object = nil
+	local current_element_name = nil
+
+	-- XML parsing handler for the start of an element
+	local function start_element_handler (parser, name)
+		current_element_name = name
+	    if name == "room" then
+			current_room_object = {}
+		elseif name == "device" then
+			current_device_object = {}
+			current_device_object["gateway_ip"] = gateway.gateway_ip
+			current_device_object["room"] = current_room_object
+        end
+	end
+
+	-- XML parsing handler for the end of an element
+	local function end_element_handler (parser, name)
+		current_element_name = name
+	    if name == "room" then
+			current_room_object = nil
+		elseif name == "device" then
+		     new_devices[#new_devices+1] = current_device_object
+			current_device_object = nil
+        end
+	end
+
+	-- XML parsing handler for the text of an element
+	local function character_handler (parser, value)
+		if current_device_object and string.find(device_elements_of_interest,"|"..current_element_name.."|") then
+		    current_device_object[current_element_name] = value
+		elseif current_room_object and (not current_device_object) and string.find(room_elements_of_interest,"|"..current_element_name.."|") then
+			current_room_object[current_element_name] = value
+        end
+	end
+
+	-- Create a parser
+	local callbacks = {StartElement = start_element_handler, EndElement = end_element_handler, CharacterData = character_handler}
+	local parser = lxp.new(callbacks)
+
+	-- Parse the XML
+	parser:parse(config_xml)
+	parser:parse() -- finishes the document
+	parser:close()
+
+	-- Save the devices, uniquely indexed by did
+	if #new_devices > 0 then
+	    for i,device in ipairs(new_devices) do
+	        gateway.devices[device.did] = device
+			-- tweak for interpretation of load level for dimmers - always set to zero if device is off
+			if device.state == "0" then
+			   device.level = "0"
+			end
+        end
+		gateway.initialized = true
+		gateway.error_text = nil
+	else
+		gateway.error_text = "No devices found at gateway " .. gateway.gateway_ip .. " while parsing " .. config_xml
+	end
+
+	return
+
+end
+
+-- ----------------------------------------------------------------------------
+-- Helper functions for testing - call devices by name/room
+-- ----------------------------------------------------------------------------
+
+function tcplighting_get_did (gateway, name, roomname)
+   local did = nil
+   for key,device in pairs(gateway.devices) do
+      if device.name == name and device.room.name == roomname then
+         did = device.did
+      end
+   end
+   return did
+end
+
+function tcplighting_set_target_by_name  (gateway, name, roomname, target_value)
+    return tcplighting_set_target(gateway, tcplighting_get_did (gateway, name, roomname), target_value)
+end
+
+function tcplighting_set_load_level_target_by_name (gateway, name, roomname, load_percent)
+    return tcplighting_set_load_level_target(gateway, tcplighting_get_did (gateway, name, roomname), load_percent)
+end
Index: /trunk/D_TCPLightingGateway1.json
===================================================================
--- /trunk/D_TCPLightingGateway1.json	(revision 3)
+++ /trunk/D_TCPLightingGateway1.json	(revision 3)
@@ -0,0 +1,95 @@
+{
+    "flashicon":      "icons/generic_sensor.swf",
+    "imgIconBody":     "",
+    "imgIconDimmable": "",
+    "imgIconTurnable": "",
+    "imgIconMin":      "",
+    "imgIconMax":      "",
+    "halloIconsDir":   "pics/hallo",
+    "inScene":         "0",
+    "DisplayStatus":   {},
+    "doc_url":
+       {
+       "doc_language": 1,
+	   "doc_manual":   1,
+       "doc_version":  1,
+       "doc_platform": 0,
+       "doc_page":     "lighting_devices"
+       },
+    "Tabs":
+	   [
+
+       {
+       "Label":    {"lang_tag": "tcp_lighting_gateway", "text": "Gateway"},
+       "Position": "0",
+       "TabType":  "flash",
+	   "SceneGroup":
+	        [
+		    {
+			"id": "1",
+			"top": "1",
+			"left": "0",
+			"x": "1",
+			"y": "1"
+		    },
+		    {
+			"id": "2",
+			"top": "2",
+			"left": "0",
+			"x": "1",
+			"y": "2"
+		    }
+		    ],
+		"ControlGroup": [
+			{
+			"id": "1",
+			"scenegroup": "1",
+			"isSingle": "1"
+			},
+			{
+			"id": "2",
+			"scenegroup": "2",
+			"type": "info"
+			}
+		],
+       "Control":
+		    [
+            {
+            "ControlType": "label",
+            "Label":       {"lang_tag": "synchronize_desc","text": "Sync to the gateway and configure lights - Gateway ip must be specified in Advanced tab"},
+            "Display":     {"Top": 20,"Left": 50,"Width": 200,"Height": 20}
+            },
+            {
+            "ControlGroup": "1",
+            "ControlType":  "button",
+            "Label":       {"lang_tag": "synchronize_command","text": "Sync"},
+			"Display":     {"Top": 37,"Left": 50, "Width": 100, "Height": 20 },
+            "Command":     {"Service": "urn:pmcode-org:serviceId:TCPLightingGateway1", "Action": "Synchronize", "Parameters": []}
+			},
+            {
+            "ControlType": "label",
+            "Label":       {"lang_tag": "error_text_label","text": "Gateway Errors:"},
+			"Display":     {"Top": 80,"Left": 50,"Width": 200, "Height": 20}
+			},
+            {
+            "ControlGroup": "2",
+            "ControlType": "variable",
+            "Display":     {"Top": 95, "Left": 70, "Width": 200, "Height": 20,
+			                "Service": "urn:pmcode-org:serviceId:TCPLightingGateway1", "Variable": "ErrorText"}
+			}
+            ]
+        },
+
+        {
+        "Label":      {"lang_tag": "advanced","text": "Advanced"},
+        "Position":   "1",
+        "TabType":    "javascript",
+        "ScriptName": "shared.js",
+        "Function":   "advanced_device"
+        }
+    ],
+    "eventList":   {},
+    "eventList2":  [],
+    "DeviceType":  "urn:schemas-pmcode-org:device:TCPLightingGateway:1",
+    "device_type": "urn:schemas-pmcode-org:device:TCPLightingGateway:1"
+}
Index: TCPLightingGateway1.xml
===================================================================
--- /S_TCPLightingGateway1.xml	(revision 1)
+++ 	(revision )
@@ -1,23 +1,0 @@
-<?xml version="1.0"?>
-<scpd xmlns="urn:schemas-upnp-org:service-1-0">
-  <specVersion>
-    <major>1</major>
-    <minor>0</minor>
-  </specVersion>
-  <serviceStateTable>
-    <stateVariable sendEvents="yes">
-      <name>Initialized</name>
-      <dataType>boolean</dataType>
-      <defaultValue>0</defaultValue>
-    </stateVariable>
-    <stateVariable sendEvents="no">
-      <name>ErrorText</name>
-      <dataType>string</dataType>
-    </stateVariable>
-  </serviceStateTable>
-  <actionList>
-    <action>
-      <name>Synchronize</name>
-    </action>
-  </actionList>
-</scpd>
Index: TCPLightingGateway1.xml
===================================================================
--- /D_TCPLightingGateway1.xml	(revision 1)
+++ 	(revision )
@@ -1,26 +1,0 @@
-<?xml version="1.0"?>
-<root xmlns="urn:schemas-upnp-org:device-1-0">
-  <specVersion>
-    <major>1</major>
-    <minor>0</minor>
-  </specVersion>
-  <device>
-    <deviceType>urn:schemas-pmcode-org:service:TCPLightingGateway:1</deviceType>
-    <staticJson>D_TCPLightingGateway1.json</staticJson>
-    <serviceList>
-      <service>
-        <serviceType>urn:schemas-pmcode-org:service:TCPLightingGateway:1</serviceType>
-        <serviceId>urn:pmcode-org:serviceId:TCPLightingGateway1</serviceId>
-        <SCPDURL>S_TCPLightingGateway1.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>
-      <implementationFile>I_TCPLighting1.xml</implementationFile>
-    </implementationList>
-  </device>
-</root>
Index: TCPLighting1.xml
===================================================================
--- /D_TCPLighting1.xml	(revision 1)
+++ 	(revision )
@@ -1,31 +1,0 @@
-<?xml version="1.0"?>
-<root xmlns="urn:schemas-upnp-org:device-1-0">
-  <specVersion>
-    <major>1</major>
-    <minor>0</minor>
-  </specVersion>
-  <device>
-    <deviceType>urn:schemas-upnp-org:device:DimmableLight:1</deviceType>
-    <staticJson>D_DimmableLight1.json</staticJson>
-    <serviceList>
-      <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-upnp-org:service:Dimming:1</serviceType>
-        <serviceId>urn:upnp-org:serviceId:Dimming1</serviceId>
-        <SCPDURL>S_Dimming1.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>
-      <implementationFile>I_TCPLighting1.xml</implementationFile>
-    </implementationList>
-  </device>
-</root>
Index: st.lua
===================================================================
--- /test.lua	(revision 1)
+++ 	(revision )
@@ -1,27 +1,0 @@
-local tcplighting = require("L_TCPLighting1")
-local json = require ("json")
-
-
--- initialize gateway
-gateway = tcplighting_gateway_init("192.168.1.110")
-print (json.encode(gateway.devices))
-
-
-
-
--- modify a light's intensity
-if (gateway.initialized) then
-    -- generate a random intensity
-	math.randomseed(os.time())
-    math.random(); math.random(); math.random()
-    local load_level_target = math.random(100)
-	--  call the gateway
-    tcplighting_set_load_level_target_by_name(gateway, "Front Entry Light", "Front Hall", load_level_target)
-    tcplighting_set_target_by_name(gateway, "Front Entry Light", "Front Hall", 1)
-	-- poll to get latest status
-    tcplighting_gateway_poll(gateway)
-    print (json.encode(gateway.devices))
-else
-    print ("--- ERROR: " .. gateway.error_text)
-end
-
Index: TCPLighting1.xml
===================================================================
--- /I_TCPLighting1.xml	(revision 1)
+++ 	(revision )
@@ -1,378 +1,0 @@
-<?xml version="1.0"?>
-<implementation>
-  <functions>
-
-       -- ---------------------------------------------------------------------
-       -- Constants
-       -- ---------------------------------------------------------------------
-       local GATEWAY_DEVICE_TYPE = "urn:schemas-pmcode-org:service:TCPLightingGateway:1"
-       local GATEWAY_SERVICE_ID  = "urn:pmcode-org:serviceId:TCPLightingGateway1"
-       local HA_DEVICE_TYPE      = "urn:schemas-micasaverde-com:service:HaDevice:1"
-       local HA_SERVICE_ID       = "urn:micasaverde-com:serviceId:HaDevice1"
-       local DIMMER_DEVICE_TYPE  = "urn:schemas-upnp-org:device:DimmableLight:1"
-       local DIMMER_SERVICE_ID   = "urn:upnp-org:serviceId:Dimming1"
-       local SWITCH_DEVICE_TYPE  = "urn:schemas-upnp-org:device:SwitchPower:1"
-       local SWITCH_SERVICE_ID   = "urn:upnp-org:serviceId:SwitchPower1"
-       local LIGHT_DEVICE_FILE   = "D_TCPLighting1.xml"
-
-
-       -- ---------------------------------------------------------------------
-       -- table respresenting the gateway and its devices
-       -- ---------------------------------------------------------------------
-       local tcplighting_gateway = nil
-
-
-       -- ---------------------------------------------------------------------
-       -- Get a reference to the gateway (will init if necessary)
-       -- ---------------------------------------------------------------------
-	   local function get_gateway (gateway_ip)
-		  if not tcplighting_gateway then
-			 tcplighting_gateway = tcplighting_gateway_init (gateway_ip)
-			 if tcplighting_gateway.error_text then
-				luup.task(tcplighting_gateway.error_text, 2, "TCPLighting", -1)
-			 end
-		  end
-		  return tcplighting_gateway
-	   end
-
-
-       -- ---------------------------------------------------------------------
-       -- Returns true if the device has dimming capabilities
-       -- ---------------------------------------------------------------------
-       local function is_dimmer_switch (device)
-           return (device and device.capability and string.find(device.capability,"switch_multilevel"))
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Returns true if the device has on/off capabilities
-       -- ---------------------------------------------------------------------
-       local function is_binary_switch (device)
-           return (device and device.capability and string.find(device.capability,"switch_binary"))
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- See if we have a matching room number
-       -- ---------------------------------------------------------------------
-       local function room_number (input_room_name)
-          local room_number = 0
-          if input_room_name then
-              for i, room_name in ipairs(luup.rooms) do
-                  if room_name == input_room_name then
-                      room_number = i
-                      break
-                  end
-              end
-          end
-          return room_number
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Sets a LUUP device variable, but only if it has no current value
-       -- ---------------------------------------------------------------------
-       local function initialize_variable (service_id, variable_name, new_value, device_number)
-          local current_value = luup.variable_get (service_id, variable_name, device_number)
-          if (not current_value) or (current_value == "") then
-              luup.variable_set (service_id, variable_name, new_value, device_number)
-          end
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Sets a LUUP device attribute, but only if it has no current value
-       -- ---------------------------------------------------------------------
-       local function initialize_attr (attr_name, new_value, device_number)
-          local current_value = luup.attr_get (attr_name, device_number)
-          if (not current_value) or (current_value == "") then
-              luup.attr_set (attr_name, new_value, device_number)
-          end
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Updates a LUUP device variable, but only if its value has changed
-       -- ---------------------------------------------------------------------
-       local function update_variable (service_id, variable_name, new_value, device_number)
-          local current_value = luup.variable_get (service_id, variable_name, device_number)
-          if (not current_value) or (new_value ~= current_value) then
-              luup.variable_set (service_id, variable_name, new_value, device_number)
-          end
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Updates a LUUP device attribute, but only if its value has changed
-       -- ---------------------------------------------------------------------
-       local function update_attr (attr_name, new_value, device_number)
-          local current_value = luup.attr_get (attr_name, device_number)
-          if (not current_value) or (new_value ~= current_value) then
-              luup.attr_set (attr_name, new_value, device_number)
-          end
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Update a device to match info from gateway
-       -- ---------------------------------------------------------------------
-       local function update_device_settings (gateway, did, lul_device)
-
-           luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - start")
-
-           if not (gateway and did and lul_device) then
-              return
-           end
-
-           -- update the device
-
-           local device_number = tonumber(lul_device)
-           local device = gateway.devices[did]
-
-           if device and device.room and device.room.name then
-               luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting room_num")
-               update_attr ("room_num", tostring(room_number(device.room.name)), device_number)
-               update_attr ("room",     tostring(room_number(device.room.name)), device_number)
-           end
-
-           if device and is_binary_switch(device) then
-               luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting Status")
-		       update_variable (SWITCH_SERVICE_ID, "Status", device.state, device_number)
-		       update_variable (SWITCH_SERVICE_ID, "Target", device.state, device_number)
-           end
-
-           if device and is_dimmer_switch(device) then
-              luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - setting LoadLevelStatus")
-		      update_variable (DIMMER_SERVICE_ID, "LoadLevelStatus", device.level, device_number)
-		      update_variable (DIMMER_SERVICE_ID, "LoadLevelTarget", device.level, device_number)
-           end
-
-           luup.log ("TCPLighting: update_device_settings for " .. lul_device .. " - end")
-
-           return
-
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Update all of the children of the specified device
-       -- ---------------------------------------------------------------------
-       local function sync_child_devices (gateway, parent_lul_device)
-
-           luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - start")
-
-           if not (gateway and parent_lul_device) then
-              return
-           end
-
-           -- poll the gateway for most current device data
-           tcplighting_gateway_poll(gateway)
-
-
-           -- find matching child devices
-           local parent_device_number = tonumber (parent_lul_device)
-           for k, luup_device in pairs(luup.devices) do
-               luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - checking device " .. k .. " ".. luup_device.description .. " with parent " .. tostring(luup_device.device_num_parent))
-               if (luup_device.device_num_parent == parent_device_number) and (luup_device.id) then
-                    luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - updating child " .. k)
-                    update_device_settings (gateway, luup_device.id, k)
-               end
-           end
-
-           luup.log ("TCPLighting: sync_child_devices for " .. parent_lul_device .. " - end")
-
-           return
-
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Create child devices of gateway if necessary
-       -- ---------------------------------------------------------------------
-       local function create_child_devices (gateway, lul_device)
-
-           luup.log ("TCPLighting: create_child_devices - start")
-
-           if gateway and gateway.initialized then
-
-              luup.log ("TCPLighting: create_child_devices - gateway is initialized")
-
-              local child_devices = luup.chdev.start (lul_device)
-
-              for did,device in pairs(gateway.devices) do
-                  if is_dimmer_switch (device) then
-                     luup.log ("TCPLighting: create_child_devices - creating dimmer child")
-                     luup.chdev.append (lul_device, child_devices, device.did, device.name, DIMMER_DEVICE_TYPE, LIGHT_DEVICE_FILE,"","",false)
-                  elseif is_binary_switch (device) then
-                     luup.log ("TCPLighting: create_child_devices - creating switch child")
-                     luup.chdev.append (lul_device, child_devices, device.did, device.name, SWITCH_DEVICE_TYPE, LIGHT_DEVICE_FILE,"","",false)
-                  end
-              end
-
-              luup.chdev.sync (lul_device, child_devices)
-
-           end
-
-		   luup.log ("TCPLighting: create_child_devices - end")
-
-       end
-
-
-       -- ---------------------------------------------------------------------
-       -- Schedule the next poll
-       -- ---------------------------------------------------------------------
-	   local function schedule_next_poll (lul_device)
-
-		   luup.log ("TCPLighting: schedule_next_poll - start")
-
-           local device_number = tonumber(lul_device)
-
-		   -- make sure the polling variables have values
-		   initialize_variable (HA_SERVICE_ID, "PollingEnabled", "true", device_number)
-		   initialize_variable (HA_SERVICE_ID, "PollMinDelay",   "60",   device_number)
-
-           -- get current polling settings (may be different from above if overriden by user)
-		   local polling_enabled  = luup.variable_get (HA_SERVICE_ID, "PollingEnabled", device_number)
-		   local polling_interval = luup.variable_get (HA_SERVICE_ID, "PollMinDelay",   device_number)
-
-		   -- make a delayed call to the synchronization functions
-		   if polling_enabled == "true" or polling_enabled == "1" then
-		      luup.call_timer("synchronize_gateway", 1, tonumber(polling_interval), "", lul_device)
-			  luup.log ("TCPLighting: schedule_next_poll - timer set")
-		   end
-
-		   luup.log ("TCPLighting: schedule_next_poll - end")
-
-	   end
-
-
-       -- ---------------------------------------------------------------------
-       -- Contact the gateway and initialize the gateway object
-       -- ---------------------------------------------------------------------
-	   function synchronize_gateway (lul_device)
-
-		   luup.log ("TCPLighting: synchronize_gateway - start")
-
-           local device_number = tonumber(lul_device)
-           local gateway_ip = luup.devices[device_number].ip
-
-           -- will create and populate a new gateway configuration object if necessary
-           local gateway = get_gateway (gateway_ip)
-
-           -- bail if there was an error
-		   if gateway.error_text then
-               update_variable (GATEWAY_SERVICE_ID, "ErrorText", gateway.error_text, device_number)
-			   return false
-		   else
-               update_variable (GATEWAY_SERVICE_ID, "ErrorText", "", device_number)
-           end
-
-           -- create and synchronize all chldren
-		   create_child_devices (gateway, lul_device)
-           sync_child_devices (gateway, lul_device)
-
-		   -- set up polling so that changes made externally to the plugin show up in the UI
-		   schedule_next_poll (lul_device)
-
-
-		   luup.log ("TCPLighting: synchronize_gateway - end")
-
-           return true
-
-	   end
-
-
-       -- ---------------------------------------------------------------------
-       -- Set the dimming level on a light
-       -- ---------------------------------------------------------------------
-       local function set_load_level_target (lul_device, lul_settings)
-	       local device_number = tonumber(lul_device)
-           local gateway_ip = luup.devices[device_number].ip
-           local did = luup.devices[device_number].id
-		   local gateway = get_gateway (gateway_ip)
-		   if gateway.initialized and did then
-               tcplighting_set_load_level_target (gateway, did, tonumber(lul_settings.newLoadlevelTarget))
-               tcplighting_gateway_poll (gateway)
-			   update_device_settings (gateway, did, lul_device)
-           end
-           return true
-	   end
-
-
-       -- ---------------------------------------------------------------------
-       -- Flips switch on/off
-       -- ---------------------------------------------------------------------
-       local function set_target (lul_device, lul_settings)
-	       local device_number = tonumber(lul_device)
-           local gateway_ip = luup.devices[device_number].ip
-           local did = luup.devices[device_number].id
-		   local gateway = get_gateway (gateway_ip)
-		   if gateway.initialized and did then
-               tcplighting_set_target (gateway, did, tonumber(lul_settings.newTargetValue))
-               tcplighting_gateway_poll (gateway)
-			   update_device_settings (gateway, did, lul_device)
-           end
-           return true
-	   end
-
-
-       -- ---------------------------------------------------------------------
-       -- Plugin startup
-       -- Will initialize the gateway, which in turn creates child devices
-       -- for each light as necessary
-       -- ---------------------------------------------------------------------
-      function tcplighting_plugin_startup (lul_device)
-
-		  luup.log ("TCPLighting: tcplighting_plugin_startup - start")
-
-	      local device_number = tonumber(lul_device)
-          local device_type = luup.devices[device_number].device_type
-
-	      if device_type == GATEWAY_DEVICE_TYPE then
-             luup.log ("TCPLighting: tcplighting_plugin_startup - is gateway")
-		     synchronize_gateway (lul_device)
-          else
-             luup.log ("TCPLighting: tcplighting_plugin_startup - not gateway")
-		  end
-
-		  luup.log ("TCPLighting: tcplighting_plugin_startup - end")
-
-	  end
-
-
-  </functions>
-
-  <startup>tcplighting_plugin_startup</startup>
-
-  <files>L_TCPLighting1.lua</files>
-
-  <actionList>
-
-    <action>
-      <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId>
-      <name>SetTarget</name>
-      <run>return set_target (lul_device, lul_settings)</run>
-    </action>
-
-    <action>
-      <serviceId>urn:upnp-org:serviceId:Dimming1</serviceId>
-      <name>SetLoadLevelTarget</name>
-      <run>return set_load_level_target (lul_device, lul_settings)</run>
-    </action>
-
-    <action>
-      <serviceId>urn:pmcode-org:serviceId:TCPLightingGateway1</serviceId>
-      <name>Synchronize</name>
-      <run>return synchronize_gateway (lul_device)</run>
-    </action>
-
-	<action>
-      <serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId>
-      <name>Poll</name>
-      <run>return synchronize_gateway (lul_device)</run>
-    </action>
-
-   </actionList>
-
-</implementation>
-
Index: TCPLighting1.lua
===================================================================
--- /L_TCPLighting1.lua	(revision 1)
+++ 	(revision )
@@ -1,238 +1,0 @@
--- ----------------------------------------------------------------------------
--- Implements urn:upnp-org:serviceId:SwitchPower1.SetTarget
--- ----------------------------------------------------------------------------
- function tcplighting_set_target (gateway, did, target_value)
-
-    local http = require("socket.http")
-
-    http.TIMEOUT = gateway.HTTP_TIMEOUT
-
-    return http.request("http://" .. gateway.devices[did].gateway_ip
-                        .. "/gwr/gop.php",
-                        "cmd=DeviceSendCommand&data="
-                        .. "<gip>"
-                        .. "<version>1</version>"
-                        .. "<token>1234567890</token>"
-                        .. "<did>" .. did .. "</did>"
-                        .. "<value>" .. target_value .. "</value>"
-                        .. "</gip>"
-                        .. "&fmt=xml")
-end
-
--- ----------------------------------------------------------------------------
--- Implements urn:upnp-org:serviceId:Dimming1.SetLoadLevelTarget
--- ----------------------------------------------------------------------------
- function tcplighting_set_load_level_target (gateway, did, load_percent)
-
-    local http = require("socket.http")
-
-    http.TIMEOUT = gateway.HTTP_TIMEOUT
-
-	-- make sure light is on/off to match request
-	if load_percent > 0 then
-	    tcplighting_set_target (gateway, did, 1)
-	else
-	    tcplighting_set_target (gateway, did, 0)
-	end
-
-	-- change the dimming level
-    return http.request("http://" .. gateway.devices[did].gateway_ip
-                        .. "/gwr/gop.php",
-                        "cmd=DeviceSendCommand&data="
-                        .. "<gip>"
-                        .. "<version>1</version>"
-                        .. "<token>1234567890</token>"
-                        .. "<did>" .. did .. "</did>"
-                        .. "<value>" .. load_percent .. "</value>"
-                        .. "<type>level</type>"
-                        .. "</gip>"
-                        .. "&fmt=xml")
-end
-
-
--- ----------------------------------------------------------------------------
--- Loads the gateway configuration
--- ----------------------------------------------------------------------------
-
- function tcplighting_gateway_init (gateway_ip)
-
- 	-- create an empty gateway object
-	local gateway = {}
-    gateway.initialized  = false
-    gateway.error_text   = "TCP Lighting Gateway not yet initialized"  -- error text for last failed operation
-	gateway.gateway_ip   = gateway_ip
-    gateway.devices      = {}    -- a cache of device info indexed by unique did
-    gateway.HTTP_TIMEOUT = 5   -- 5 seconds should be fine on a local network
-
-	-- Make sure a gateway ip was specified
-	if not gateway_ip or string.len(gateway_ip) == 0 then
-	   gateway.error_text = "No gateway IP address specified"
-	   return gateway
-	end
-
-	-- Get the gateway's configuration data
-    tcplighting_gateway_poll (gateway)
-
-	return gateway
-
-end
-
--- ----------------------------------------------------------------------------
--- Get current values from the gateway
--- ----------------------------------------------------------------------------
-
- function tcplighting_gateway_poll (gateway)
-
-   	-- Get the gateway's configuration data
-    local result, status = tcplighting_get_gateway_config (gateway)
-
-	-- Check the HTTP status
-    if status ~= 200 then
-	   gateway.error_text = "HTTP gateway query request to " .. gateway.gateway_ip .. " failed"
-	   if status then gateway.error_text = gateway.error_text .. " - " .. status     end
-	   if result then gateway.error_text = gateway.error_text .. " - " .. result     end
-	   return
-	end
-
-	-- Make sure something came back
-	if not result then
-	   gateway.error_text = "HTTP gateway query request to " .. gateway.gateway_ip .. " did not return any data"
-	   return
-	end
-
-    -- Only parse if the HTTP request was successful
-    tcplighting_parse_gateway_config(gateway, result)
-    return
-
-end
-
--- ----------------------------------------------------------------------------
--- Queries a Connected by TCP Gateway to determine which lights are available
--- ----------------------------------------------------------------------------
- function tcplighting_get_gateway_config (gateway)
-
-    local http = require("socket.http")
-
-    http.TIMEOUT = gateway.HTTP_TIMEOUT
-
-    return http.request("http://" .. gateway.gateway_ip
-                        .. "/gwr/gop.php",
-                        "cmd=GWRBatch&data="
-                        .. "<gwrcmds>"
-                        .. "<gwrcmd>"
-                        .. "<gcmd>RoomGetCarousel</gcmd>"
-                        .. "<gdata>"
-                        .. "<gip>"
-                        .. "<version>1</version>"
-                        .. "<token>1234567890</token>"
-                        .. "<fields>name,image,imageurl,control,power,product,class,realtype,status</fields>"
-                        .. "</gip>"
-                        .. "</gdata>"
-                        .. "</gwrcmd>"
-                        .. "</gwrcmds>"
-                        .. "&fmt=xml")
-end
-
-
--- ----------------------------------------------------------------------------
--- Parse the gateway configuration
--- ----------------------------------------------------------------------------
-
- function tcplighting_parse_gateway_config (gateway, config_xml)
-
-	local lxp = require("lxp")
-	local json = require ("json")
-
-	-- Local collection devices - will be added to master table after parsing
-	local new_devices = {}
-
-	-- enumerate the XML elements that we want to load into our tables
-	local room_elements_of_interest = "|rid|name|desc|"
-	local device_elements_of_interest = "|did|name|desc|state|level|type|rangemin|rangemax|power|poweravg|energy|manufacturer|prodbrand|prodmodel|prodtype|capability|"
-
-	-- used to keep track of the current context during the parsing process
-    local current_room_object = nil
-	local current_device_object = nil
-	local current_element_name = nil
-
-	-- XML parsing handler for the start of an element
-	local function start_element_handler (parser, name)
-		current_element_name = name
-	    if name == "room" then
-			current_room_object = {}
-		elseif name == "device" then
-			current_device_object = {}
-			current_device_object["gateway_ip"] = gateway.gateway_ip
-			current_device_object["room"] = current_room_object
-        end
-	end
-
-	-- XML parsing handler for the end of an element
-	local function end_element_handler (parser, name)
-		current_element_name = name
-	    if name == "room" then
-			current_room_object = nil
-		elseif name == "device" then
-		     new_devices[#new_devices+1] = current_device_object
-			current_device_object = nil
-        end
-	end
-
-	-- XML parsing handler for the text of an element
-	local function character_handler (parser, value)
-		if current_device_object and string.find(device_elements_of_interest,"|"..current_element_name.."|") then
-		    current_device_object[current_element_name] = value
-		elseif current_room_object and (not current_device_object) and string.find(room_elements_of_interest,"|"..current_element_name.."|") then
-			current_room_object[current_element_name] = value
-        end
-	end
-
-	-- Create a parser
-	local callbacks = {StartElement = start_element_handler, EndElement = end_element_handler, CharacterData = character_handler}
-	local parser = lxp.new(callbacks)
-
-	-- Parse the XML
-	parser:parse(config_xml)
-	parser:parse() -- finishes the document
-	parser:close()
-
-	-- Save the devices, uniquely indexed by did
-	if #new_devices > 0 then
-	    for i,device in ipairs(new_devices) do
-	        gateway.devices[device.did] = device
-			-- tweak for interpretation of load level for dimmers - always set to zero if device is off
-			if device.state == "0" then
-			   device.level = "0"
-			end
-        end
-		gateway.initialized = true
-		gateway.error_text = nil
-	else
-		gateway.error_text = "No devices found at gateway " .. gateway.gateway_ip .. " while parsing " .. config_xml
-	end
-
-	return
-
-end
-
--- ----------------------------------------------------------------------------
--- Helper functions for testing - call devices by name/room
--- ----------------------------------------------------------------------------
-
-function tcplighting_get_did (gateway, name, roomname)
-   local did = nil
-   for key,device in pairs(gateway.devices) do
-      if device.name == name and device.room.name == roomname then
-         did = device.did
-      end
-   end
-   return did
-end
-
-function tcplighting_set_target_by_name  (gateway, name, roomname, target_value)
-    return tcplighting_set_target(gateway, tcplighting_get_did (gateway, name, roomname), target_value)
-end
-
-function tcplighting_set_load_level_target_by_name (gateway, name, roomname, load_percent)
-    return tcplighting_set_load_level_target(gateway, tcplighting_get_did (gateway, name, roomname), load_percent)
-end
Index: TCPLightingGateway1.json
===================================================================
--- /D_TCPLightingGateway1.json	(revision 1)
+++ 	(revision )
@@ -1,95 +1,0 @@
-{
-    "flashicon":      "icons/generic_sensor.swf",
-    "imgIconBody":     "",
-    "imgIconDimmable": "",
-    "imgIconTurnable": "",
-    "imgIconMin":      "",
-    "imgIconMax":      "",
-    "halloIconsDir":   "pics/hallo",
-    "inScene":         "0",
-    "DisplayStatus":   {},
-    "doc_url":
-       {
-       "doc_language": 1,
-	   "doc_manual":   1,
-       "doc_version":  1,
-       "doc_platform": 0,
-       "doc_page":     "lighting_devices"
-       },
-    "Tabs":
-	   [
-
-       {
-       "Label":    {"lang_tag": "tcp_lighting_gateway", "text": "Gateway"},
-       "Position": "0",
-       "TabType":  "flash",
-	   "SceneGroup":
-	        [
-		    {
-			"id": "1",
-			"top": "1",
-			"left": "0",
-			"x": "1",
-			"y": "1"
-		    },
-		    {
-			"id": "2",
-			"top": "2",
-			"left": "0",
-			"x": "1",
-			"y": "2"
-		    }
-		    ],
-		"ControlGroup": [
-			{
-			"id": "1",
-			"scenegroup": "1",
-			"isSingle": "1"
-			},
-			{
-			"id": "2",
-			"scenegroup": "2",
-			"type": "info"
-			}
-		],
-       "Control":
-		    [
-            {
-            "ControlType": "label",
-            "Label":       {"lang_tag": "synchronize_desc","text": "Sync to the gateway and configure lights - Gateway ip must be specified in Advanced tab"},
-            "Display":     {"Top": 20,"Left": 50,"Width": 200,"Height": 20}
-            },
-            {
-            "ControlGroup": "1",
-            "ControlType":  "button",
-            "Label":       {"lang_tag": "synchronize_command","text": "Sync"},
-			"Display":     {"Top": 37,"Left": 50, "Width": 100, "Height": 20 },
-            "Command":     {"Service": "urn:pmcode-org:serviceId:TCPLightingGateway1", "Action": "Synchronize", "Parameters": []}
-			},
-            {
-            "ControlType": "label",
-            "Label":       {"lang_tag": "error_text_label","text": "Gateway Errors:"},
-			"Display":     {"Top": 80,"Left": 50,"Width": 200, "Height": 20}
-			},
-            {
-            "ControlGroup": "2",
-            "ControlType": "variable",
-            "Display":     {"Top": 95, "Left": 70, "Width": 200, "Height": 20,
-			                "Service": "urn:pmcode-org:serviceId:TCPLightingGateway1", "Variable": "ErrorText"}
-			}
-            ]
-        },
-
-        {
-        "Label":      {"lang_tag": "advanced","text": "Advanced"},
-        "Position":   "1",
-        "TabType":    "javascript",
-        "ScriptName": "shared.js",
-        "Function":   "advanced_device"
-        }
-    ],
-    "eventList":   {},
-    "eventList2":  [],
-    "DeviceType":  "urn:schemas-pmcode-org:device:TCPLightingGateway:1",
-    "device_type": "urn:schemas-pmcode-org:device:TCPLightingGateway:1"
-}
