Index: /I_WeMo1.xml
===================================================================
--- /I_WeMo1.xml	(revision 1)
+++ /I_WeMo1.xml	(revision 3)
@@ -8,4 +8,5 @@
 	this_plugin = require ("L_WeMo1")
 	reentry = this_plugin.reentry
+	cancelProxySubscription = this_plugin.cancelProxySubscription
 	return this_plugin.initialize (lul_device)
 end
Index: /L_WeMo1.lua
===================================================================
--- /L_WeMo1.lua	(revision 1)
+++ /L_WeMo1.lua	(revision 3)
@@ -375,9 +375,15 @@
 		local duration = headers["timeout"]:match("Second%-(%d+)")
 		debug("Subscription confirmed, SID = " .. headers["sid"] .. " with timeout " .. duration, 2)
-		return headers["sid"], duration
+		return headers["sid"], tonumber(duration)
 	end
 end
 
 -- getProxyApiVersion()
+-- Calls the proxy with GET /version.
+-- Sets the ProxyApiVersion Luup variable to the value received
+-- (or the empty string).
+-- Return value:
+--   nil if the proxy is not running.
+--   The proxy API version (as a string) otherwise.
 function getProxyApiVersion()
 	local sock = function()
@@ -411,4 +417,6 @@
 end
 
+-- proxyVersionAtLeast(n)
+-- Returns true if the proxy is running and is at least version n.
 function proxyVersionAtLeast(n)
 	if (ProxyApiVersion and tonumber(ProxyApiVersion:match("^(%d+)")) >= n) then
@@ -418,4 +426,12 @@
 end
 
+-- informProxyOfSubscription(deviceId)
+-- Sends a PUT /upnp/event/[sid] message to the proxy,
+-- asking it to inform this plugin if the BinaryState
+-- UPnP variable changes.
+-- Return value:
+--   nil if the proxy timed out (should try again).
+--   false if the proxy refused our request (permanently).
+--   true if the proxy agreed to our request.
 function informProxyOfSubscription(deviceId)
 	debug("Informing proxy of subscription for device " .. deviceId, 2)
@@ -440,5 +456,5 @@
 		method = "PUT",
 		headers = {
-			["Content-Type"] = "text/html",
+			["Content-Type"] = "text/xml",
 			["Content-Length"] = proxyRequestBody:len(),
 		},
@@ -458,4 +474,40 @@
 end
 
+-- cancelProxySubscription(sid)
+-- Sends a DELETE /upnp/event/[sid] message to the proxy,
+-- Return value:
+--   nil if the proxy timed out (should try again).
+--   false if the proxy refused our request (permanently).
+--   true if the proxy agreed to our request.
+function cancelProxySubscription(sid)
+	debug("Cancelling unwelcome subscription for sid " .. sid, 2)
+	local sock = function()
+		local s = socket.tcp()
+		s:settimeout(2)
+		return s
+	end
+
+	local request, code = http.request({
+		url = "http://localhost:2529/upnp/event/" .. url.escape(sid),
+		create = sock,
+		method = "DELETE",
+		source = ltn12.source.empty(),
+		sink = ltn12.sink.null(),
+	})
+	if (request == nil and code ~= "closed") then
+		debug("Failed to cancel subscription: " .. code, 2)
+		return nil
+	elseif (code ~= 200) then
+		debug("Failed to cancel subscription: " .. code, 2)
+		return false
+	else
+		debug("Successfully cancelled subscription", 2)
+		return true
+	end
+end
+
+-- queueAction(delay, retries, action)
+-- Remember to run the function in action (with no parameters)
+-- in delay seconds.  Allow only the specified number of retries.
 function queueAction(delay, retries, action)
 	table.insert(FutureActionQueue, {
@@ -466,4 +518,11 @@
 end
 
+-- renewSubscription(deviceId)
+-- Try to renew the UPnP subscription for the child device deviceId.
+-- Return value:
+--   nil if the renewal request timed out (and we should retry).
+--   false if the renewal was refused (permanently).
+--   true if the renewal was accepted (a later renewal will be
+--     queued and the proxy will be informed).
 function renewSubscription(deviceId)
 	debug("Renewing subscription for device " .. deviceId, 2)
@@ -512,10 +571,12 @@
 		end
 	end
-
-end
-
+end
+
+-- schedule()
+-- Ask the plugin to sleep for as many seconds as
+-- the next event (or five minutes, if there are no events).
 function schedule()
 	-- How long to sleep?
-	local delay = 3600
+	local delay = 300
 	for i = 1, #FutureActionQueue do
 		if (FutureActionQueue[i].time <= os.time()) then
@@ -529,4 +590,8 @@
 end
 
+-- reentry()
+-- This function will be called when a sleep from
+-- schedule() completes.  In theory, one of the queued actions
+-- is now ready to perform.
 function reentry()
 	local action = nil
@@ -538,4 +603,5 @@
 	end
 
+	-- Clock skew might mean there is no action.
 	if (action) then
 		local result = action.action()
@@ -745,4 +811,6 @@
 	end
 	debug("SID does not match: expected " .. ChildDevices[lul_device].sid .. ", got " .. sid)
+  -- Try to shut the proxy up, we don't care about this SID.
+	luup.call_delay("cancelProxySubscription", 1, sid)
 	return false
 end
@@ -833,4 +901,5 @@
 
 -- handleSetTarget(lul_device, newTargetValue)
+-- Called when the user asks to turn on or off a switch.
 function handleSetTarget(lul_device, newTargetValue)
 	debug("Setting Target = " .. newTargetValue .. " for device " .. lul_device)
@@ -861,5 +930,2 @@
 	return false
 end
-
-function processTimerQueue()
-end
