Index: /tags/0.1/S_GCal.xml
===================================================================
--- /tags/0.1/S_GCal.xml	(revision 3)
+++ /tags/0.1/S_GCal.xml	(revision 3)
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+  <specVersion>
+    <major>1</major>
+    <minor>0</minor>
+  </specVersion>
+  <serviceStateTable>
+    <stateVariable sendEvents="no">
+      <name>gcallink</name>
+      <datatype>string</datatype>
+      <defaultValue></defaultValue>
+    </stateVariable>
+     <stateVariable sendEvents="no">
+      <name>gcalon</name>
+      <datatype>string</datatype>
+      <defaultValue>ON</defaultValue>
+    </stateVariable>
+  </serviceStateTable>
+  <actionList>
+    <action>
+      	<name>GCalCheck</name>
+    </action>
+    <action>
+      	<name>SetGCalLink</name>
+      	<argumentList>
+         <argument>
+          <name>NewGCalLink</name>
+          <direction>in</direction>
+         </argument>
+      </argumentList>
+    </action>
+    <action>
+      <name>SetGCalOn</name>
+      <argumentList>
+        <argument>
+          <name>NewGCalOn</name>
+          <direction>in</direction>
+        </argument>
+      </argumentList>
+    </action>
+  </actionList>
+</scpd>
Index: /tags/0.1/D_GCal.xml
===================================================================
--- /tags/0.1/D_GCal.xml	(revision 3)
+++ /tags/0.1/D_GCal.xml	(revision 3)
@@ -0,0 +1,32 @@
+<?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-utz-com:device:GCal:1</deviceType>
+    <staticJson>D_GCal.json</staticJson>
+    <serviceList>
+	<service>
+		<serviceType>urn:schemas-utz-com:service:GCal:1</serviceType>
+		<serviceId>urn:utz-com:serviceId:GCal1</serviceId>
+		<SCPDURL>S_GCal.xml</SCPDURL>
+	</service>
+	<service>
+		<serviceType>urn:schemas-micasaverde-com:service:SecuritySensor:1</serviceType>
+		<serviceId>urn:micasaverde-com:serviceId:SecuritySensor1</serviceId>
+		<SCPDURL>S_SecuritySensor1.xml</SCPDURL>
+	</service>
+    </serviceList>
+    <friendlyName>GCal Sensor</friendlyName>
+    <serialNumber>123456789001</serialNumber>
+    <UDN>uuid:gcal-1234567890001</UDN>
+    <UPC>123456789</UPC>
+    <handleChildren>0</handleChildren>
+    <implementationList>
+      <implementationFile>I_GCal.xml</implementationFile>
+    </implementationList>
+    <presentationURL>/gcal.html</presentationURL>
+   </device>
+</root>
Index: /tags/0.1/J_GCal.js
===================================================================
--- /tags/0.1/J_GCal.js	(revision 3)
+++ /tags/0.1/J_GCal.js	(revision 3)
@@ -0,0 +1,21 @@
+function calendarTab(device){
+	var html = '';
+
+	var src = get_device_state(device, "urn:utz-com:serviceId:GCal1", "gcalsrc", 0);
+
+	html += '<iframe src="https://www.google.com/calendar/embed?';
+	html += 'showPrint=0&amp;';
+	html += 'showTabs=0&amp;';
+	html += 'showCalendars=0&amp;';
+	html += 'showTz=0&amp;';
+	html += 'mode=WEEK&amp;';
+	html += 'height=500&amp;';
+	html += 'wkst=1&amp;';
+	html += 'bgcolor=%23FFFFFF&amp;';
+	html += 'src=' + src + '%40group.calendar.google.com&amp;';
+	html += 'color=%23711616&amp"';
+	html += ' style=" border-width:0 " width="600" height="350" frameborder="0" scrolling="no"></iframe>';
+	
+	set_panel_html(html);
+}
+
Index: /tags/0.1/I_GCal.xml
===================================================================
--- /tags/0.1/I_GCal.xml	(revision 3)
+++ /tags/0.1/I_GCal.xml	(revision 3)
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<implementation>
+  <functions>
+      local GCAL_VERSION 	= "V 0.10"
+      local LOG_DEBUG 		= true
+      local UPDATE_FREQU 	= 5
+      local GCAL_SID 	 	= "urn:utz-com:serviceId:GCal1"
+      local SECURITY_SID 	= "urn:micasaverde-com:serviceId:SecuritySensor1"
+      
+      -- Control debug to /var/log/cmh/LuaUPnP.log (taken from GE Caddx Panel)
+      function debug(s)
+	if (LOG_DEBUG) then
+		luup.log(s)
+	end
+      end
+
+      -- Added by sjolshagen to handle timezones
+      function get_timezone()
+	  local now = os.time()
+	  return os.difftime(now, os.time(os.date("!*t", now)))
+      end
+
+      -- check if an event with name gcalon is scheduled in the calendar gcallink
+      function checkGCal()
+	local gcallink	= luup.variable_get(GCAL_SID, "gcallink", lul_device)
+	local gcalon	= luup.variable_get(GCAL_SID, "gcalon", lul_device)
+	if ((gcallink~=nil) and (gcalon~=nil)) then		
+		debug("GCAL: checking google calendar")
+		local url = gcallink .. "?alt=json&amp;fields=entry/title"
+		local t = os.time(t)
+		t = t - get_timezone()
+		local ta = os.date('!*t')
+		ta.isdst=true 
+		local s = string.format("%d-%02d-%02dT%02d:%02d:%02d", ta.year, ta.month, ta.day, ta.hour, ta.min, ta.sec)
+		debug("GCAL: start-min: " .. s)
+		url = url .. "&amp;start-min=" .. s
+		t = t+(UPDATE_FREQU*60)
+		ta = os.date('*t', t)
+		s = string.format("%d-%02d-%02dT%02d:%02d:%02d", ta.year, ta.month, ta.day, ta.hour, ta.min, ta.sec)
+		debug("GCAL: start-max: " .. s)
+		url = url .. "&amp;start-max=" .. s
+		local status, page = luup.inet.wget(url, 10)
+		debug("GCAL: query url: " .. url)
+		debug("GCAL: query status: " .. status)
+	        if (status == 0) then
+			luup.log("GCAL: query result: " .. page)
+			if( string.find (page, gcalon)~=nil ) then
+	      			debug("GCAL: an event with name " .. gcalon .. " is currently active")				
+				local gcalval=string.match(page, gcalon.."{([A-Za-z0-9]+)}.*$")
+				if (gcalval~=nil) then
+					debug("GCAL: attached value: " .. gcalval)
+					luup.variable_set(GCAL_SID, "gcalval", gcalval, lul_device)
+				else
+					debug("GCAL: no value attached")
+					luup.variable_set(GCAL_SID, "gcalval", "", lul_device)
+				end
+				luup.variable_set(SECURITY_SID, "Tripped", 1, lul_device)
+			else
+				debug("GCAL: no event with name " .. gcalon .. " is currently active")
+				luup.variable_set(SECURITY_SID, "Tripped", 0, lul_device)
+			end
+ 		end
+	end	
+      end
+      
+      -- check calendar with frequency UPDATE_FREQU
+      function GCalTimer(stuff)
+	luup.call_timer("GCalTimer", 1, UPDATE_FREQU.."m", "", "")
+	checkGCal()
+      end
+
+      -- startup
+      function GCalStartup(lul_device)
+	luup.call_timer("GCalTimer", 1, UPDATE_FREQU.."m", "", "")
+	checkGCal()
+      end
+
+  </functions>
+  <incoming>
+	<lua>
+		luup.log(string.format("GCAL: incoming should not be called on this device"))
+	</lua>
+  </incoming>
+  <startup>GCalStartup</startup>
+  <actionList>
+  <action>
+     <serviceId>urn:micasaverde-com:serviceId:SecuritySensor1</serviceId>
+     <name>SetArmed</name>
+     <run>
+	luup.variable_set(SECURITY_SID, "Armed", lul_settings.newArmedValue, lul_device)
+     </run>
+  </action>
+  <action>      
+     <serviceId>urn:utz-com:serviceId:GCal1</serviceId>
+     <name>GCalCheck</name>
+     <run>
+	luup.log(string.format("GCAL: check calendar"))
+	checkGCal()
+     </run>
+  </action>
+  <action>
+     <serviceId>urn:utz-com:serviceId:GCal1</serviceId>
+     <name>SetGCalLink</name>
+     <run>
+	luup.log(string.format("GCAL: set calendar link (gcallink)"))
+	local gcalsrc = lul_settings.NewGCalLink:match("^http://www.google.com/calendar/feeds/(.*)@group.*$")
+	luup.log(string.format("GCAL: src="..gcalsrc))
+	luup.variable_set(GCAL_SID, "gcalsrc", gcalsrc, lul_device)
+       	luup.variable_set(GCAL_SID, "gcallink", lul_settings.NewGCalLink, lul_device)
+     </run>
+  </action>
+  <action>
+     <serviceId>urn:utz-com:serviceId:GCal1</serviceId>
+     <name>SetGCalOn</name>
+     <run>
+	luup.log(string.format("GCAL: set calendar keyword (gcalon)"))
+       	luup.variable_set(GCAL_SID, "gcalon", lul_settings.NewGCalOn, lul_device)
+     </run>
+   </action>
+  </actionList>
+</implementation>
Index: /tags/0.1/D_GCal.json
===================================================================
--- /tags/0.1/D_GCal.json	(revision 3)
+++ /tags/0.1/D_GCal.json	(revision 3)
@@ -0,0 +1,313 @@
+{
+    "flashicon": "icons\/Motion_Sensor.swf",
+    "imgIconBody": "",
+    "imgIconDimmable": "",
+    "imgIconTurnable": "",
+    "imgIconMin": "",
+    "imgIconMax": "",
+    "halloIconsDir": "pics\/hallo",
+    "DisplayStatus": {
+        "Service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+        "Variable": "Tripped",
+        "MinValue": "0",
+        "MaxValue": "1" 
+    },
+    "doc_url": {
+        "doc_language": 1,
+        "doc_manual": 1,
+        "doc_version": 1,
+        "doc_platform": 0,
+        "doc_page": "devices" 
+    },
+    "ToggleButton": 1,
+    "Tabs": [
+	{
+	"Label": {
+                "lang_tag": "tabname_control",
+                "text": "Control" 
+            },
+            "Position": "0",
+            "TabType": "flash",
+	    "ControlGroup":[
+		{
+			"id":"1",
+			"isSingle":"1"
+		},
+		{
+			"id":"2",
+			"isSingle":"1"
+		}
+            ],
+            "Control": [
+                {
+		    "ControlGroup":"1",
+                    "ControlType": "button",
+                    "Label": {
+                        "lang_tag": "cmd_arm",
+                        "text": "Arm" 
+                    },
+                    "Display": {
+                        "Service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                        "Variable": "Armed",
+                        "Value": "1",
+                        "Top": 50,
+                        "Left": 50,
+                        "Width": 75,
+                        "Height": 20 
+                    },
+                    "Command": {
+                        "Service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                        "Action": "SetArmed",
+                        "Parameters": [
+                            {
+                                "Name": "newArmedValue",
+                                "Value": "1" 
+                            } 
+                        ] 
+                    } 
+                },
+                {
+	  	    "ControlGroup":"2",
+                    "ControlType": "button",
+                    "Label": {
+                        "lang_tag": "cmd_bypass",
+                        "text": "Bypass" 
+                    },
+                    "Display": {
+                        "Service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                        "Variable": "Armed",
+                        "Value": "0",
+                        "Top": 50,
+                        "Left": 150,
+                        "Width": 75,
+                        "Height": 20 
+                    },
+                    "Command": {
+                        "Service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                        "Action": "SetArmed",
+                        "Parameters": [
+                            {
+                                "Name": "newArmedValue",
+                                "Value": "0" 
+                            } 
+                        ] 
+                    } 
+                },
+		{
+                    "ControlType": "button",
+                    "Label": {
+                        "lang_tag": "GCalCheck",
+                        "text": "Check" 
+                    },
+                    "Display": {
+                        "Top": 50,
+                        "Left": 250,
+                        "Width": 75,
+                        "Height": 20
+                    },
+                    "Command": {
+                        "Service": "urn:utz-com:serviceId:GCal1",
+                        "Action": "GCalCheck",
+                    } 
+                },
+		{
+			"ControlType": "label",
+			"Label": {
+				"lang_tag": "gcallink",
+				"text": "Link"
+			},
+			"Display": {
+				"Top": 100,
+				"Left": 50,
+				"Width": 75,
+				"Height": 20
+			}
+		},
+		{
+			"ControlType":"input",
+			"ID": "NewGCalLink",
+			"Display":{
+				"Top": 100,
+				"Left":150,
+				"Width": 300,
+				"Height": 20
+			}
+		},
+		{
+			"ControlType": "button",
+			"Label": {
+				"lang_tag": "setgcallink",
+				"text": "Set"
+			},
+			"Display": {
+				"Top": 100,
+				"Left": 500,
+				"Width": 75,
+				"Height": 20
+			},
+			"Command": {
+				"Service": "urn:utz-com:serviceId:GCal1",
+				"Action":  "SetGCalLink",
+				"Parameters": [
+					{
+						"Name": "NewGCalLink",
+						"ID": "NewGCalLink"
+					}
+				]
+			}
+		},
+		{
+			"ControlType": "label",
+			"Label": {
+				"lang_tag": "gcalon",
+				"text": "Keyword"
+			},
+			"Display": {
+				"Top": 150,
+				"Left": 50,
+				"Width": 75,
+				"Height": 20
+			}
+		},
+		{
+			"ControlType":"input",
+			"ID": "NewGCalOn",
+			"Display":{
+				"Top": 150,
+				"Left":150,
+				"Width": 300,
+				"Height": 20
+			}
+		},
+		{
+			"ControlType": "button",
+			"Label": {
+				"lang_tag": "setgcalon",
+				"text": "Set"
+			},
+			"Display": {
+				"Top": 150,
+				"Left": 500,
+				"Width": 75,
+				"Height": 20
+			},
+			"Command": {
+				"Service": "urn:utz-com:serviceId:GCal1",
+				"Action":  "SetGCalOn",
+				"Parameters": [
+					{
+						"Name": "NewGCalOn",
+						"ID": "NewGCalOn"
+					}
+				]
+			}
+		}
+            ] 
+        },
+	{
+	    "Label": {
+            	"lang_tag": "calendar",
+            	"text": "Calendar"
+            },
+           "Position": "2",
+           "TabType": "javascript",
+           "ScriptName": "J_GCal.js",
+           "Function": "calendarTab"
+	    },
+        {
+            "Label": {
+                "lang_tag": "advanced",
+                "text": "Advanced" 
+            },
+            "Position": "3",
+            "TabType": "javascript",
+            "ScriptName": "shared.js",
+            "Function": "advanced_device" 
+        },
+	{
+            "Label": {
+            	"lang_tag": "notifications",
+                "text": "Notifications" 
+            },
+            "Position": "4",
+            "TabType": "javascript",
+            "ScriptName": "shared.js",
+            "Function": "device_notifications" 
+        }
+    ],
+    "sceneList": {
+        "group_1": {
+            "cmd_1": {
+                "label": "Arm",
+                "serviceId": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                "action": "SetArmed",
+                "arguments": {
+                    "newArmedValue": "1" 
+                },
+                "display": {
+                    "service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                    "variable": "Armed",
+                    "value": "1"
+                } 
+            },
+            "cmd_2": {
+                "label": "Bypass",
+                "serviceId": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                "action": "SetArmed",
+                "arguments": {
+                    "newArmedValue": "0" 
+                },
+                "display": {
+                    "service": "urn:micasaverde-com:serviceId:SecuritySensor1",
+                    "variable": "Armed",
+                    "value": "0"
+                } 
+            } 
+        } 
+    },
+    "eventList": {
+        "event_1": {
+            "label": "A calendar event is active",
+            "serviceId": "urn:micasaverde-com:serviceId:SecuritySensor1",
+            "argumentList": {
+                "argument_1": {
+                    "dataType": "boolean",
+                    "defaultValue": "",
+                    "allowedValueList": {
+                        "On": "1",
+                        "Off": "0" 
+                    },
+                    "name": "Tripped",
+                    "comparisson": "=",
+                    "prefix": "Status?",
+                    "suffix": " " 
+                } 
+            } 
+        },
+        "event_2": {
+            "label": "An armed calendar event is active",
+            "serviceId": "urn:micasaverde-com:serviceId:SecuritySensor1",
+            "serviceStateTable": {
+                "Armed": {
+                    "value": "1",
+                    "comparisson": "=" 
+                } 
+            },
+            "argumentList": {
+                "argument_1": {
+                    "dataType": "boolean",
+                    "allowedValueList": {
+                        "On": "1",
+                        "Off": "0" 
+                    },
+		    "name": "Tripped",
+                    "comparisson": "=",
+                    "prefix": "Status?",
+                    "suffix": " "
+                } 
+            } 
+        }
+    },
+    "DeviceType": "urn:schemas-utz-com:device:GCal:1",
+    "device_type": "urn:schemas-utz-com:device:GCal:1" 
+}
