Index: /RTSPrototype/veraTemplateTest.lua
===================================================================
--- /RTSPrototype/veraTemplateTest.lua	(revision 3)
+++ /RTSPrototype/veraTemplateTest.lua	(revision 3)
@@ -0,0 +1,108 @@
+module("veraTemplateTest", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+function test()
+   local t = require("veraTemplate")
+   t.Absent = 2
+
+   require("veraTemplateDefinitions")
+   if (not pcall(require, "veraUserTemplateDefinitions")) then
+      print("Sorry Can't find: veraUserTemplateDefinitions.lua")
+   end
+
+   -- Set the Default Device
+   local d = require("veraTemplateDevice")
+   d.device = 20
+
+   print("Parse Classes:")
+   print(t.classes())
+
+   -- Various Expansions
+
+   print(t.expand("Test Number 3.14159  !"))
+   print(t.expand("Test Number String Format {String.format(%20.2e,3.14159)}  !"))
+   print(t.expand("Test Number with Pipe to String.Format1 {Number(3.14159) | String(%20.2e)}  !"))
+   print(t.expand("Test Number {Number(3.14159,%20.2e)}  !"))
+
+   print(t.expand("Test DateTime CurrentTime {dAtEtIme(currenttime)}  !"))
+   print(t.expand("Test DateTime Format CurrentTime {DateTime(currenttime,%A %B %d %Y %H:%M)}  !"))
+   print(t.expand("Test DateTime Format Past Time {DateTime(1111100000,{DateTimeFormat})}  !"))
+
+   print(t.expand("Test String Upper {String.upper(AbCdEfG)}  !"))
+   print(t.expand("Test String Lower {String.lower(AbCdEfG)}  !"))
+   print(t.expand("Test String RFill {String.rfill(AbCdEfG   ,R,20)}  !"))
+   print(t.expand("Test String RFill {String.rfill(AbCdEfG   ,R,2)}  !"))
+   print(t.expand("Test String LFill {String.lfill(   AbCdEfG,L,20)}  !"))
+   print(t.expand("Test String LFill {String.lfill(   AbCdEfG,L,2)}  !"))
+   print(t.expand("Test String Truncate {String.truncate(AbCdEfG,3)}  !"))
+   print(t.expand("Test String Format {String.format(%20s %-20s,String 1,String 2)}  !"))
+   print(t.expand("Test String Format with Pipe {String.format(%20s %-20s,String 1,String 2) | String.lfill(L,1) | String.rfill(R,1)}  !"))
+   print(t.expand("Test String Format with NewLines {String.format(\n%s  !\n%20s  !\n%-20s,Text Line 1,Text Line2,Text Line 3)}  !"))
+
+   print(t.expand("Test System {System(city)}  !"))
+
+   print(t.expand("Test Choose 0 {Choose(0, {LockOptions})} !"))
+   print(t.expand("Test Choose 1 {Choose(1, {LockOptions})} !"))
+   print(t.expand("Test Choose 2 {Choose(2, {LockOptions})} !"))
+   
+   print(t.expand("Test Device {device}  !"))
+   print(t.expand("Test Device {device(description)}  !"))
+   print(t.expand("Test Device {device(room)}  !"))
+   print(t.expand("Test Device {device(room.name)}  !"))
+   print(t.expand("Test Device {device(service[foobar].Status)}  !"))
+   print(t.expand("Test Device {device(service[urn:upnp-org:serviceId:SwitchPower1].Status)}  !"))
+   print(t.expand("Test Device {device(switch.Status)}  !"))
+
+   print(t.expand("Test Device {device([5])}  !"))
+   print(t.expand("Test Device {device([5].description)}  !"))
+   print(t.expand("Test Device {device([5]room)}  !"))
+   print(t.expand("Test Device {device([5].room.name)}  !"))
+   print(t.expand("Test Device {device([5].service[foobar].Status)}  !"))
+   print(t.expand("Test Device {device([5].service[urn:upnp-org:serviceId:SwitchPower1].Status)}  !"))
+   print(t.expand("Test Device {device([5].Switch.Status)}  !"))
+
+   print(t.expand("Test Device {device([Office Light])}  !"))
+   print(t.expand("Test Device {device([Office Light].description)}  !"))
+   print(t.expand("Test Device {device([Office Light].room)}  !"))
+   print(t.expand("Test Device {device([Office Light].room.name)}  !"))
+   print(t.expand("Test Device {device([Office Light].service[foobar].Status)}  !"))
+   print(t.expand("Test Device {device([Office Light].service[urn:upnp-org:serviceId:SwitchPower1].Status)}  !"))
+   print(t.expand("Test Device {device([Office Light].Switch.Status)}  !"))
+
+   print(t.expand("Test Device {device([9].parent)}  !"))
+   print(t.expand("Test Device {device([9].parent.description)}  !"))
+   print(t.expand("Test Device {device([9].parent.room)}  !"))
+   print(t.expand("Test Device {device([9].parent.room.name)}  !"))
+   print(t.expand("Test Device {device([9].parent.service[foobar].Status)}  !"))
+   print(t.expand("Test Device {device([9].parent.service[urn:upnp-org:serviceId:SwitchPower1].Status)}  !"))
+   print(t.expand("Test Device {device([9].parent.Switch.Status)}  !"))
+
+   print(t.expand("Test Device {device([9].service[urn:upnp-org:serviceId:SwitchPower1].Status)} !"))
+   print(t.expand("Test Device {device([9].service[urn:upnp-org:serviceId:SwitchPower1].Status) | Choose(0=Off,1=On,Other=Unknown)}  !"))
+   print(t.expand("Test Device {device([9].service[urn:upnp-org:serviceId:SwitchPower1].Status) | Choose({BinarySwitchOptions})}  !"))
+   
+   print(t.expand("Test Device {device([9].Switch.Status)}  !"))
+   print(t.expand("Test Device {device([9].Switch.Status) | Choose(0=Off,1=On,Other=Unknown)}  !"))
+   print(t.expand("Test Device {device([9].Switch.Status) | Choose({BinarySwitchOptions})}  !"))
+
+   print(t.expand("Test Device & DateTime Choose Nested Template: {device([9].description)} last update on {DateTime({device([9].HomeAutomation.LastUpdate)}, !{DateTimeFormat})} GMT !"))
+   print(t.expand("Test Device & DateTime Switch Pipe through Choose: {device([9].description)} last update on {device([9].HomeAutomation.LastUpdate) |  DateTime(!{DateTimeFormat})} GMT !"))
+end
Index: /RTSPrototype/veraTemplateNumber.lua
===================================================================
--- /RTSPrototype/veraTemplateNumber.lua	(revision 3)
+++ /RTSPrototype/veraTemplateNumber.lua	(revision 3)
@@ -0,0 +1,42 @@
+module("veraTemplateNumber", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+-- Private ------------------------------------------------------------------------
+local ParseArgs = "([%-]?[%d%.]+)[%,%s]*([%s%S]*)"
+-- Public ------------------------------------------------------------------------
+templateclass="Number"
+
+function expand(SubFunction, Args, PipeArg)
+   local data, format
+   if (PipeArg) then
+      data = PipeArg
+      format = Args
+   else
+      local s, f
+      s, f, data, format = string.find(Args, ParseArgs)
+   end
+   local res = data
+   if (format and (string.len(format) > 0)) then
+      res = string.format(format, data)
+   end
+   --print("Number SubFunction:" .. (SubFunction or "nil") .. " Args:" .. (Args or "nil") .. " data:" .. (data or "nil") .. " format:" .. (format or "nil").. " res:" .. (res or "nil"))
+   return res
+end
Index: /RTSPrototype/veraTemplate.lua
===================================================================
--- /RTSPrototype/veraTemplate.lua	(revision 3)
+++ /RTSPrototype/veraTemplate.lua	(revision 3)
@@ -0,0 +1,144 @@
+module("veraTemplate", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+-- Private ------------------------------------------------------------------------
+local Version = "1.0.1"
+local TemplatePattern =  "%b{}"
+local TemplateClasses = {}
+
+-- p1 = Class, p2 = SunFunction, p3 = Junk upto ( or |) p4 = rest
+local ParseTemplateStruncture  = "^[%s]*([%w]+)([%.%w]*)([^%(%|]*)([%s%S]*)$"
+
+local function ExpandATemplate(Dict, Text, PipeArg)  
+   --Log("ExpandATemplate",  "Dict:" .. Dict .. " Text:" .. Text .. " PipeArg:" .. (PipeArg or "nil"))
+   local s,f,Class,SubFunction,p3,p4 = string.find(Text, ParseTemplateStruncture)
+   local Args
+   local Rest
+   local exp
+   if (p4 and string.find(p4,"^%(")) then
+      s,f,Args = string.find(p4, "(%b())[%s]*")
+      Args = string.sub(Args, 2, -2)
+      Rest = string.sub(p4, f+1)
+      --Log("ExpandATemplate",  "Rest:" .. (Rest or "nil"))
+   end
+   if (SubFunction and (string.len(SubFunction) > 0)) then
+      SubFunction = string.sub(SubFunction, 2)
+   end
+   
+   local DictVal = TemplateClasses["Template"]
+   local t = DictVal[string.lower(Class)]
+   if (t) then
+      if (type(t) == "string") then
+         exp = t
+      else
+         exp = t.expand(string.lower(SubFunction), Args, PipeArg)
+      end
+      --Log("ExpandATemplate",  "Dict:" .. Dict .. " Class:" .. Class .. " SubFunction:" .. (SubFunction or "nil") .. " Args:" .. (Args or "nil")  .. " Result:" .. (exp or "nil"))
+   else
+      -- Pass thru unknow stuff
+      return
+   end
+   
+   if (Rest and string.len(Rest) > 0) then
+      -- We are Chained ... Parse the next component
+      exp = ExpandATemplate(Dict, string.sub(Rest,2),  exp)
+   end
+   return exp
+end
+
+-- Public ------------------------------------------------------------------------
+-- Absent  Defines the behaviour of a template that does not expand  (0: Untouched, 1: Remove Braces, 2: Empty String)
+Absent = 0
+
+function expand(txt, Dict)
+   local Dict  = Dict or "Template"
+   return(string.gsub(txt, TemplatePattern, 
+                      function(Text) 
+                         local exp = ExpandATemplate(Dict, expand(string.sub(Text,2,-2)))
+                         --Log("Expand:",  tostring(exp) .. " Absent:" .. tostring(Absent))
+                         if (exp) then
+                            exp = tostring(exp)
+                         else
+                            if (Absent == 1) then
+                               exp = string.sub(Text,2,-2)
+                            elseif (Absent == 2) then
+                               exp = "";
+                            end
+                         end
+                         return exp
+                      end))
+end
+
+
+function register(Template, Definition, Dict)
+   Dict = Dict or "Template"
+   local DictTab = TemplateClasses[Dict]
+   if (not DictTab) then
+      DictTab = {}
+   end
+   if (type(Template) == "string" )  then
+      --print("Register String: " .. Template .. " Dict:"  .. Dict)
+      DictTab[string.lower(Template)] = Definition
+   else
+      --print("Register Class: " .. Template.templateclass)
+      DictTab[string.lower(Template.templateclass)] = Template
+   end
+   TemplateClasses[Dict] = DictTab
+end
+
+function lookup(Template, Dict)
+   Dict = Dict or "Template"
+   local DictTab = TemplateClasses[Dict]
+   return DictTab[string.lower(Template)]
+end
+
+function classes()
+   local s = ""
+   local DictKey
+   local DictVal
+   for DictKey, DictVal in pairs(TemplateClasses) do
+      local ClassKey
+      local ClassVal
+      for ClassKey, ClassVal in pairs(DictVal) do
+         s  = s .. DictKey .. ": {" .. ClassKey
+         if (type(ClassVal) == "string") then
+            s = s .. "} = \"" .. ClassVal .. "\""
+         else
+            s = s .. "} is a functional template"
+         end
+         s = s .. "\n"
+      end
+   end
+   return s
+end
+
+function version()
+   return(Version)
+end
+
+-- Standard Classes
+
+register(require("veraTemplateString"));
+register(require("veraTemplateDateTime"));
+register(require("veraTemplateDevice"));
+register(require("veraTemplateSystem"));
+register(require("veraTemplateNumber"));
+register(require("veraTemplateChoose"));
Index: /RTSPrototype/veraTemplateDefinitions.lua
===================================================================
--- /RTSPrototype/veraTemplateDefinitions.lua	(revision 3)
+++ /RTSPrototype/veraTemplateDefinitions.lua	(revision 3)
@@ -0,0 +1,47 @@
+module("veraTemplateDefinitions", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+local t = require("veraTemplate")
+-- Define some Service aliases  
+t.register("HomeAutomation", "service[urn:micasaverde-com:serviceId:HaDevice1]", "Service")
+t.register("ZWave", "service[urn:micasaverde-com:serviceId:ZWaveNetwork1]", "Service")
+t.register("Energy", "service[urn:micasaverde-com:serviceId:EnergyMetering1]", "Service")
+t.register("Switch", "service[urn:upnp-org:serviceId:SwitchPower1]", "Service")
+t.register("Dimmer", "service[urn:upnp-org:serviceId:Dimming1]", "Service")
+t.register("Lock", "service[urn:micasaverde-com:serviceId:DoorLock1]", "Service")
+t.register("Security", "service[urn:micasaverde-com:serviceId:SecuritySensor1]", "Service")
+t.register("HVACMode", "service[urn:upnp-org:serviceId:HVAC_UserOperatingMode1]", "Service")
+t.register("HVACState", "service[urn:micasaverde-com:serviceId:HVAC_OperatingState1]", "Service")
+t.register("HVACCool", "service[urn:upnp-org:serviceId:TemperatureSetpoint1_Cool]", "Service")
+t.register("HVACHeat", "service[urn:upnp-org:serviceId:TemperatureSetpoint1_Heat]", "Service")
+t.register("HVACFan", "service[urn:upnp-org:serviceId:HVAC_FanOperatingMode1]", "Service")
+t.register("Blind", "service[urn:upnp-org:serviceId:WindowCovering1]", "Service")
+t.register("TemperatureSensor", "service[urn:upnp-org:serviceId:TemperatureSensor1]", "Service")
+t.register("LightSensor", "service[urn:upnp-org:serviceId:LightSensor1]", "Service")
+t.register("HumiditySensor", "service[urn:upnp-org:serviceId:HumiditySensor1]", "Service")
+
+-- Define some translation templates
+
+t.register("BinarySwitchOptions", "0=Off,1=On,Other=Unknown")
+t.register("LockOptions", "0=Unlock,1=Lock,Other=Unknown")
+
+-- Define  DateTimeFormat
+t.register("DateTimeFormat", "%A %B %d %Y %H:%M")
Index: /RTSPrototype/veraTemplateChoose.lua
===================================================================
--- /RTSPrototype/veraTemplateChoose.lua	(revision 3)
+++ /RTSPrototype/veraTemplateChoose.lua	(revision 3)
@@ -0,0 +1,47 @@
+module("veraTemplateChoose", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+-- Private ------------------------------------------------------------------------
+
+-- Public ------------------------------------------------------------------------
+templateclass="Choose"
+
+function expand(SubFunction, Args, PipeArg)
+   local maps = {}
+   local data, oprions
+   if (PipeArg) then
+      data = PipeArg
+      options = Args
+   else
+      data, options = string.match(Args, "([^,]+)%,([%s%S]*)")
+   end
+   local res = data
+   if (data) then
+      string.gsub(options, "[%s]*([^,]+)%=([^,]+)", 
+		  function(s,t) 
+		     maps[s] = t 
+		  end)
+      res = maps[res] or maps["Other"] or res
+   end
+   --print("Choose SubFunction:" .. (SubFunction or "nil") .. " Args:" .. (Args or "nil") .. " res:" .. (res or "nil"))
+   return res
+end
+
Index: /RTSPrototype/veraTemplateSystem.lua
===================================================================
--- /RTSPrototype/veraTemplateSystem.lua	(revision 3)
+++ /RTSPrototype/veraTemplateSystem.lua	(revision 3)
@@ -0,0 +1,38 @@
+module("veraTemplateSystem", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+-- Private ------------------------------------------------------------------------
+
+-- Public ------------------------------------------------------------------------
+templateclass="System"
+
+-- Should never pipe into system
+function expand(SubFunction, Args, PipeArg)
+   local s,f,vname = string.find(Args, "([%w]+)")
+   local res
+   if (luup == nil) then
+      res =  "luup." .. vname
+   else
+      res =  luup[vname]
+   end
+   --print("System SubFunction:" .. (SubFunction or "nil") .. " Args:" .. (Args or "nil") .. " vname:" .. (vname or "nil") .. " res:" .. (res or "nil"))
+   return res
+end
Index: /RTSPrototype/veraTemplateDevice.lua
===================================================================
--- /RTSPrototype/veraTemplateDevice.lua	(revision 3)
+++ /RTSPrototype/veraTemplateDevice.lua	(revision 3)
@@ -0,0 +1,142 @@
+module("veraTemplateDevice", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+-- Private ------------------------------------------------------------------------
+
+local function RoomProperty(dev, Args) 
+   --print ("Device.RoomProperty: " .. dev .. " Args:" .. Args)
+   local room
+   local res
+   if (luup) then
+      room = luup.devices[tonumber(dev)].room_num
+   else
+      room = "luup.devices[" .. dev .. "].room_num"
+   end
+   if (string.lower(Args) == 'name') then
+      if (luup) then
+	 res = luup.rooms[room]
+      else
+	 res = "luup.rooms[" .. room .. "]"
+      end
+   else
+      res = room
+   end
+   return res
+end
+
+local function SrvcProperty(dev, Srvc, Args)
+   --print ("Device.SrvcProperty: " .. dev .. " Srvc:" .. Srvc .. " Args:" .. Args)
+   local res
+   if (luup) then
+      res = luup.variable_get(Srvc, Args, tonumber(dev))
+   else
+      res = "luup.variable_get(" .. Srvc .. ", " .. Args .. ", " ..  dev .. ")"
+   end
+   return res
+end
+
+local function PropertyRead(dev, Args)
+   --print("Device.PropertyRead:" .. dev .. " Args:" .. Args)
+   local s, f, srvc  = string.find(Args, "^service(%b[])")
+   if (srvc) then
+      res = SrvcProperty(dev, string.sub(srvc,2,-2), string.sub(Args, string.len(srvc) + 9))
+   else
+      local s, f, field = string.find(Args, "^[%s]*([%w]*)[%.%s%p]*")
+      Args =  string.sub(Args, f + 1)
+      local lfield = string.lower(field)
+      if (lfield == 'room') then
+	 res = RoomProperty(dev,  Args)
+      else
+	 -- Check if Field is a service alias
+	 local t = require("veraTemplate")
+	 local s = t.lookup(field, "Service")
+	 if (s) then
+	    res = PropertyRead(dev, s .. "."  .. Args)
+	 else
+	    --- Must be a device property
+	    if (luup) then
+	       res = luup.devices[tonumber(dev)][field]
+	    else
+	       res =  "luup.devices[" .. dev .. "]." ..  field
+	    end
+	 end
+      end
+   end
+   return  res
+end
+
+
+local function DevRead(dev, Args)
+   -- print("Device.DevRead:" .. dev .. " Args:" .. Args);
+   local s, f = string.find(Args,  "^parent[%.%s%p]*")
+   local res
+   if (f) then
+      if (luup) then
+	 dev = luup.devices[dev].parent
+      else
+	 dev = "luup.devices[" .. dev .. "].parent"
+      end
+      res = DevRead(dev, string.sub(Args, f+1))
+   else
+      if (string.len(Args) > 0) then
+	 res = PropertyRead(dev, Args)
+      else
+	 res = dev
+      end
+   end
+   return res
+end
+
+
+-- Public ------------------------------------------------------------------------
+templateclass="Device"
+device = 0
+
+-- Should never pipe into Device
+function expand(SubFunction, Args, PipeArg)
+   Args = Args or ""
+   local s, f, dev, rest = string.find(Args, "^(%b[])[%s%.]*([%s%S]*)")
+   if (dev) then
+      dev = string.sub(dev, 2, -2)
+   else 
+      dev = tostring(device)
+      rest = Args
+   end
+   local devnum = tostring(tonumber(dev))
+   if (dev ~= devnum) then
+      if (luup) then
+	 for i,d in ipairs(luup.devices) do
+	    if (d.description == dev) then
+	       dev = i
+	       break
+	    end
+	 end
+      else
+	 dev = "Lookup(" .. dev .. ")"
+      end
+   end
+   local res = dev
+   if (string.len(rest) > 0) then
+      res = DevRead(dev, rest)
+   end
+   --Log("veraTemplateDevice", "SubFunction:" .. (SubFunction or "nil") .. " Args:" .. (Args or "nil") .." rest:" .. (rest or "nil") .." res:" .. (res or "nil"))
+   return res
+end
Index: /RTSPrototype/veraTemplateDateTime.lua
===================================================================
--- /RTSPrototype/veraTemplateDateTime.lua	(revision 3)
+++ /RTSPrototype/veraTemplateDateTime.lua	(revision 3)
@@ -0,0 +1,47 @@
+module("veraTemplateDateTime", package.seeall)
+--
+-- Vera Template Library
+-- Copyright (C) 2012 Richard T. Schaefer
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2
+-- of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+----------------------------------------------------
+
+-- Private ------------------------------------------------------------------------
+local ParseArgs = "([%d%w]+)[%,%s]*([%s%S]*)"
+
+-- Public ------------------------------------------------------------------------
+templateclass="DateTime"
+
+function expand(SubFunction, Args, PipeArg)
+   local data, format
+   if (PipeArg) then
+      data = PipeArg
+      format = Args
+   else
+      local s, f 
+      s, f, data, format = string.find(Args, ParseArgs)
+   end
+   local res
+   if (data and (string.lower(data) == "currenttime")) then
+      data = os.time()
+   end
+   res = data
+   if (format and (string.len(format) > 0)) then
+      res = os.date(format, tonumber(data))
+   end
+   --print("DateTime SubFunction:" .. (SubFunction or "nil") .. " Args:" .. (Args or "nil") .. " data:" .. (data or "nil") .. " format:" .. (format or "nil").. " res:" .. (res or "nil"))
+   return res
+end
