Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

 


Tip
iconfalse


 Related docs
IP device APIs 
Composite attributes 
Helper tags 
HTTP Invoke 




Tip
iconfalse


 Related docs
Device Manager 
Macros 
Execute Query Macro 
Multiple Invokes 



 

Hardware Setup

Image Modified

Philip Hue is a system of 4 components:

  1. Apps – These are ways to control the lights to make them do smart things. 
  2. Bridge – This is used to enable your smart bulbs to communicate with each other and the Portal via the internet. The main set of APIs are those offered by the bridge. These allow you to control all settings of the lights in your system. These APIs require direct access to your bridge so you’ll only be able to access them when your app and bridge are on the same local network.
  3. Portal – This is a web based control panel which connects your home to the internet. It delivers control commands from outside and keeps your software in the bridge up-to-date. The portal presents a utility API to help you discover the address of your bridge.
  4. Lights – This is the output of the system. These smart bulbs contain 3 types of LED specifically chosen to produce a range of colors and intensities. Lights create a mesh network with each other which enables each light to pass on messages to the next extending the range and making everything more robust. They are connected to the bridge via an open standards protocol called ZigBee Light Link.

We will be controlling the lights using Philip Bridge HTTP APIs.

Philip Bridge HTTP Requests

http://10.0.2.16/api/newdeveloper/lights

Request Name: Get the list of lights

Code Block
titleGet Lights JSON
linenumberstrue
{
    "1": {
        "state": {
            "on": true,
            "bri": 144,
            "hue": 13088,
            "sat": 212,
            "effect": "none",
            "xy": [
                0.5128,
                0.4147
            ],
            "ct": 467,
            "alert": "none",
            "colormode": "hs",
            "reachable": true
        },
        "type": "Extended color light",
        "name": "Hue Lamp 1",
        "modelid": "LCT001",
        "uniqueid": "00:17:88:01:00:b6:c6:f0-0b",
        "swversion": "66009663",
        "pointsymbol": {
            "1": "none",
            "2": "none",
            "3": "none",
            "4": "none",
            "5": "none",
            "6": "none",
            "7": "none",
            "8": "none"
        }
    },
    "2": {
        "state": {
            "on": true,
            "bri": 144,
            "hue": 13088,
            "sat": 212,
            "effect": "none",
            "xy": [
                0.5128,
                0.4147
            ],
            "ct": 467,
            "alert": "none",
            "colormode": "ct",
            "reachable": true
        },
        "type": "Extended color light",
        "name": "Hue Lamp 2",
        "modelid": "LCT001",
        "uniqueid": "00:17:88:01:00:b9:38:7c-0b",
        "swversion": "66009663",
        "pointsymbol": {
            "1": "none",
            "2": "none",
            "3": "none",
            "4": "none",
            "5": "none",
            "6": "none",
            "7": "none",
            "8": "none"
        }
    },
    "3": {
        "state": {
            "on": true,
            "bri": 144,
            "hue": 13088,
            "sat": 212,
            "effect": "none",
            "xy": [
                0.5128,
                0.4147
            ],
            "ct": 467,
            "alert": "none",
            "colormode": "hs",
            "reachable": true
        },
        "type": "Extended color light",
        "name": "Hue Lamp 3",
        "modelid": "LCT001",
        "uniqueid": "00:17:88:01:00:b9:38:5c-0b",
        "swversion": "66009663",
        "pointsymbol": {
            "1": "none",
            "2": "none",
            "3": "none",
            "4": "none",
            "5": "none",
            "6": "none",
            "7": "none",
            "8": "none"
        }
    }
}

Request Name:  Change the state of Light

http://10.0.2.16/api/newdeveloper/lights/1/state

Code Block
titleGet Lights JSON
linenumberstrue
{"on":true}

Write a ThingFacet, Workflow and Device Logic (Message Transformation)

Write a ThingFacet 

To abstract the interactions with the Philip Light Bulbs, we create a PhilipLightFacet ThingFacet. 

...

titleThingFacet

...

We add two types of attributes in this ThingFacet

  1. Parameters required to make a protocol specific invocation 

 

Attributes to store the information received from the light. 

There are two important patterns

...

to look for:

...

Mapping of Device Vendor Complex Structure: The response from GetLights is a complex hierarchical response.

...

Helper Tags: Tags that are helpful in simplifying long name as well as parameterizing the Protocol Parameters instead of attributes of a ThingFacet

 

Let's create

...

Types (Def) to match to the response structure of Lights REST API

Code Block
languagexml
titlePhilipLightState Definition
linenumberstrue
<Def Name="PhilipLightState">
  <Boolean Name="On"/>
  <Integer Name="bri"/>
  <Integer Name="hue"/>
  <Integer Name="sat"/>
  <String Name="effect"/>
  <Double Name="xy" cardinality="2"/>
  <Integer Name="ct"/>
  <String Name="alert"/>
  <String Name="colormode"/>
  <Boolean Name="reachable"/>
</Def>

Helper Tag - 1: Simply define the Philip Light Bridge API URL using PhilipLightBaseURI Tag

Code Block
languagexml
titlePhilipLightBaseURI Tag
linenumberstrue
<PhilipLightBaseURI>http://10.0.2.16/api/newdeveloper</PhilipLightBaseURI>

Lets now create a ThingFacet using the PhilipLightState type and rest of the parameters like - Type, modelId, etc as parameters of the PhilipLightFacet ThingFacet. Now the entire ThingFacet definition maps to the exact Response of the GetLight structure.

Helper Tag - 2: Tag AA to designate Event.Argument

Code Block
languagexml
titlePhilipLightBaseURI Tag
linenumberstrue
 <ThingFacet Name="PhilipLightFacet">
  <String Name="LightNumber"/>
  <PhilipLightState Name="State"/>
  <String Name="Type"/>
  <String Name="modelid"/>
  <String Name="uniqueid"/>
  <String Name="swversion"/>
  <!-- Helper Tag -->
  <AA>[:#o#Event.Argument:]</AA>
 </ThingFacet>

Write a Action with Workflow

The next step in ThingFacet is writing a Action which contains a workflow responsible for making external protocol specific call and store the output in the appropriate ThingFacet attribute.  An important decision while writing Action is correct protocol selection. See the /wiki/spaces/TQLDocs/pages/1179871 in the Working with Things section. For this Philip Light we need simple HTTP request, which is part of the TQLEngine.

1. Write an Action name as PhilipLightAction

Code Block
languagexml
titlePhilipLightAction
linenumberstrue
<ThingFacet Name="

...

PhilipLightFacet">
	...
	<Action Name="PhilipLightAction">
		...
	</Action>
</ThingFacet>

...

titleAction

...

 

2. Create a Workflow within the Action, with one single continuous running Task and waiting for the Event with its ActionArgument.

Code Block
language

...

xml
titleWorkflow

...

Go to page

...

titleWorkflow structure

...

Go to page

linenumberstrue
<Action Name="PhilipLightAction">
	<Workflow Limit="1" Live="1" Timeout="-1">
    	<Task name="Main" while="true">
        	<Event name="Argument" as="ActionArgument"/>
			...
    	</Task>
	</Workflow>
</Action>

Here we used three modifiers for this workflow. Limit = "1" means there can be at most one instance of this workflow waiting. Live = "1" means there can be at most one instance of this workflow running. Timeout ="-1" means this workflow will never be timed out. We used a modifier while = "true" with the Task to make the workflow running in a continuous loop, because it needs to run repeatedly, not just once. For more details, refer to workflow modifiers and the lifecycle of a workflow.

The task will be activated by the event handler Event called ActionArgument. "ActionArgument" is the event generated whenever the attribute(s) associated with this Action is modified (See Associate Action with a ThingFacet Attribute). ActionArgument carries all the current values of the ThingFacet attributes, which can be used in the task if needed.

 

...

titleActionArgument

...

3. Invoke HTTP call: Method of HTTP is PUT. We use Invoke modifier Put for this purpose. The parameters required for HTTP PUT are passed as part of <Message> and <Value>.

...

languagexml
titleInvoke HTTP Handler
linenumberstrue

Note that: xmlns="something" is added to disable tag normalization. Tag normalization is performed any time an XML (or JSON) text is converted into a ListMap structure. To prevent normalization you can specify a non-default XML namespace on the element you want normalization to be disabled. Example: <Message xmlns="PLight" to disable normalization for the whole query).

Code Block
languagexml
titleInvoke HTTP Handler
linenumberstrue
<Invoke Name="SetState" waitFor="ActionArgument" Put="[:PhilipLightBaseURI:]/lights/[%:[:AA:].LightNumber.Value:%]/state">

...


  <Message 

...

xmlns="

...

PLight"

...

 Type="json">
    <on_true>
      <on>true</on>
    </on_true>
    <on_false>
      <on>false</on>
    </on_false>
    <Value>

...


      <Include>[:@WFRT:]on_[%:[:AA:].state.On.Value

...

:%]</

...

Include>
    </Value>
  </Message>
</Invoke>

Note that PhilipLightBaseURI is referenced using TP tag: [:PhilipLightBaseURI:] The notation [%: is part of the /wiki/spaces/TEACH/pages/21170773. More details on /wiki/spaces/TEACH/pages/21170773 can be found in the Developer's Guide.

...

4. Process the message received from the Philip Light Bridge

...

languagexml
titleMessage parsing using TP and XPath

...

TagResolution
[:PhilipLightBaseURI:]
http://10.0.2.16/api/newdeveloper
[:AA:]
Event.Argument
[%:[:AA:].

...

LightNumber.Value:%]

...

 

...

Associate Action with a ThingFacet Attribute

We will now have to associate a ThingFacet Attribute (State) with the Action using the KnownBy modifier. When State is "KnownBy" PhilipLightAction, any State value changes will activate the PhilipLightAction.

Code Block
languagexml
titleAttribute State tied to Action
linenumberstrue
<ThingFacet Name="PhilipLightAction">
	...
    <PhilipLightState Name="State" KnownBy="PhilipLightActionUsingPut"/>
</ThingFacet>

...

titleActionable attributes

...

Go to page

The attribute modifier update= "auto" makes sure that once the action associated with this attribute is triggered, its workflow continues to run and wait for subsequent sensor events (not just the first event). This modifier is only used with actionable attributes. For more details, refer to Automatic Action trigger.

Combining ThingFacet with a ThingModel

...

Runtime value of structure: Event.Argument.LightNumber.Value
<on_true> and <on_false>contains <on>true</on> and <on>false</on>; this is stop gap to avoid string to boolean conversion in TP
[:@WFRT:]

Delay processing of Tags at Workflow execution time. Note the TQLEngine goes through number of

processing / pre-processing phases. Prefixing it with WFRT tells the Engine to delay resolving the Tags until

the execution of the workflow

[%:[:AA:].state.On.Value:%]
Runtime value of structure: Event.Argument.state.On.Value
<Include>[:@WFRT:]on_[%:[:AA:].state.On.Value:%]</Include>Includes the content of either <on_true> or <on_false>


4. Process the message received from the Philip Light Bridge

Code Block
languagexml
titleMessage parsing using TP and XPath
<Output name="Result" as="ActionResult">
   <Value>
     <State>
        <On>[%:[:AA:].state.Value:%]</On>
     </State>
  </Value>
</Output>

 

Anchor
Associate Action with a ThingFacet Attribute
Associate Action with a ThingFacet Attribute

Associate Action with a ThingFacet Attribute

We will now have to associate a ThingFacet Attribute (State) with the Action using the KnownBy modifier. When State is "KnownBy" PhilipLightAction, any State value changes will activate the PhilipLightAction.

Code Block
languagexml
title

...

Attribute State tied to Action
linenumberstrue

...

<ThingFacet Name

...

="PhilipLightFacet">
	...
    

...

<PhilipLightState Name="State" KnownBy="

...

PhilipLightAction"/>
</

...

titleModels

...

Go to page

...

titleThingModels

...

Go to page

 

...

ThingFacet>

The attribute modifier update= "auto" makes sure that once the action associated with this attribute is triggered, its workflow continues to run and wait for subsequent sensor events (not just the first event). This modifier is only used with actionable attributes. For more details, refer to Automatic Action trigger.

Combining ThingFacet with a ThingModel

Finally, in order to use ThingFacet we have to combine it with a ThingModel. We define ThingModel to contain only a unique system identifier.

Code Block
languagexml
titleThingModel PhilipLightModel
linenumberstrue
 <ThingModel Name="PhilipLightModel" Combines="PhilipLightFacet">
 <Sid Name="LightId"/>
</ThingModel>

 

PhilipLightFacet can only be instantiated (and write TQL Queries) when it is combined with PhilipLightModel. PhilipLightModel will inherit all the attributes from PhilipLightFacet, in addition to its own attributes. The ThingFacet

...

PhilipLightFacet hence serves as a reusable component.

More details on the use of "combines" can be found here. Information on Sid can be found here.

Deploy and test via queries and subscriptions

Export, import and deploy

Once the models are built in a TQLStudio project, you can export the project. The URL of the Zip file containing the content of your project will be sent over to your email account. Once you have downloaded the engine – launch the TQLEngine User Interface in the browser and select Import Project. You can copy the URL from Export Project Email and hit import button. Go to ThingSpaces and Deploy the project.

...

titleDeploy and instantiate

...

Go to page

Instantiation

Here we use a query to instantiate the sensor, creating 1 instance of the TempSensor ThingModel. In the query, we first use "DeleteAll" to delete all the current instances of the TempSensor, if there are any. The Save will save the values into the corresponding model attributes  (inherited from the ThingFacet). These values provide the runtime parameters for the perif:// handler, as well as providing an update of the TempValue actionable attribute ($Null ( )), which will trigger the associated action SerialReadAction.

Code Block
languagexml
titleSensor instantiation
linenumberstrue
<Query>
	<DeleteAll format="version,current">
    	<TempSensor>
      		<sensorId ne=""/>
    	</TempSensor>
  	</DeleteAll>
  	<Save format="version,current">
    	<!-- This will read -->
    	<TempSensor>
      		<Peripheral>serial</Peripheral>
      		<Baudrate>9600</Baudrate>
      		<InterfacePort>/dev/cu.usbserial-AL01C1HO</InterfacePort>
      		<Interface>serial</Interface>
      		<Format>ascii</Format>
      		<Operation>receive</Operation>
      		<UniqueId>76522</UniqueId>
      		<Payload>$Null()</Payload>
      		<TempValue>$Null()</TempValue>
    	</TempSensor>
  	</Save>
</Query>

Query and subscription

Now we can try a simple Find Query to get sensor values

...

languagexml
titleFind TempSensor query
linenumberstrue

...

Initializing Lights

Typically ThingModels are instantiated by writing external Create or Save Queries. In this case the Lights data is itself coming from another Provider API. Number of device vendors follow the pattern of providing metadata loading APIs. This is a common approach. In PhilipLight example, we can load PhilipLightModel data by invoking HTTP Get on Lights. Let's create another ThingFacet and ThingModel for the purpose of loading the data. We also have to call the Create Query within the ThingFacet.

The building blocks to Loading Lights are:

  • Ability to run Create TQL Query from ThingFacet
  • Ability to Load lights at any given time

TQLEngine allows us to run TQL Queries from the Model itself using <OnRequest> Tag. We need to provide the Target ID to make this request. Since queries can be called any number of times, it is always a good idea to wrap calling of a TQL Query in a generic Macro Definition. Let's call this ExecuteQuery.

Generic Macro to Execute a TQL Query

Code Block
languagexml
titleMacro Definition to run any Query
linenumberstrue
<Macro Name="ExecuteQuery">
   <Argument>
     <QueryString>
       <Query/>
     </QueryString>
    </Argument>
    <Result>
      <OnRequest>
        <Target>[:RuntimeParams.FacetIDName:]</Target>
         <Process>
           <Message>
             <Value>[:$Macro.Argument.QueryString:]</Value>
           </Message>
         </Process>
       </OnRequest>
    </Result>
</Macro>

Macro to Create Light

Since creating of light can be called multiple times, we can wrap the creating of Light itself in another Macro definition called AddLight. In AddLight we can in turn use ExecuteQuery Macro.

Code Block
languagexml
titleAddLight Macro
linenumberstrue
<Macro Name="AddLight">
      <Argument>
        <LightNumber/>
        <On/>
        <bri/>
        <hue/>
        <sat/>
      </Argument>
      <Result>
        <ExecuteQuery>
          <QueryString>
            <DeleteAll>
              <PhilipLightModel>
                <LightNumber Eq="[:$Macro.Argument.LightNumber:]"/>
              </PhilipLightModel>
            </DeleteAll>
            <Create>
              <PhilipLightModel>
                <LightNumber>[:$Macro.Argument.LightNumber:]</LightNumber>
                <State>
                  <On>[:$Macro.Argument.On:]</On>
                  <bri>[:$Macro.Argument.bri:]</bri>
                  <hue>[:$Macro.Argument.hue:]</hue>
                  <sat>[:$Macro.Argument.sat:]</sat>
                </State>
              </PhilipLightModel>
            </Create>
          </QueryString>
        </ExecuteQuery>
      </Result>
</Macro>

ThingFacet to Load Lights

We need a trigger mechanism to load the lights. For this purpose we can write another PhilipLightManagerFacet ThingFacet with an LoadLightsAction Action against a LoadLights Attribute. This ThingFacet is similar to any other ThingFacet except that the Invoke is to the AddLight Macro using FacetScript.

Code Block
languagexml
titlePhilipLightManagerFacet
linenumberstrue
<ThingFacet Name="PhilipLightManagerFacet">
      <String Name="LoadLights" KnownBy="LoadLightsAction"/>
      <Action Name="LoadLightsAction">
        <Workflow Limit="1" Live="1" Timeout="-1">
          <Task Name="Main" While="True">
            <Event Name="Argument" As="ActionArgument"/>
            <Invoke Name="GetLights" waitFor="ActionArgument" Get="[:PhilipLightBaseURI:]/lights"/>
            <Log Message="Lights Loaded...[:Invoke.GetLights.Message.Value:]"/>
            <Invoke Name="ParseGetLightsResult">
              <FacetScript>
                <AddLight>
                  <LightNumber>1</LightNumber>
                  <On>[:Invoke.GetLights.Message.Value.1.State.On:]</On>
                  <bri>[:Invoke.GetLights.Message.Value.1.State.bri:]</bri>
                  <hue>[:Invoke.GetLights.Message.Value.1.State.hue:]</hue>
                  <sat>[:Invoke.GetLights.Message.Value.1.State.sat:]</sat>
                </AddLight>
                <AddLight>
                  <LightNumber>2</LightNumber>
                  <On>[:Invoke.GetLights.Message.Value.2.State.On:]</On>
                  <bri>[:Invoke.GetLights.Message.Value.2.State.bri:]</bri>
                  <hue>[:Invoke.GetLights.Message.Value.2.State.hue:]</hue>
                  <sat>[:Invoke.GetLights.Message.Value.2.State.sat:]</sat>
                </AddLight>
             

...

 

...

 

...

 <AddLight>
       

...

     

...

 

...

You will see the result from the RESULTS window:

...

languagexml
titleFind TempSensor query result
linenumberstrue
collapsetrue

...

 

...

 

...

   <LightNumber>3</LightNumber>
 

...

         

...

        <On>[:Invoke.GetLights.Message.Value.3.State.On:]</On>
    

...

             

...

 <bri>[:Invoke.GetLights.Message.Value.3.State.bri:]</bri>
                 

...

 <hue>[:Invoke.GetLights.Message.Value.3.State.hue:]</hue>
            

...

 

...

 

...

    

...

<sat>[:Invoke.GetLights.Message.Value.3.State.sat:]</sat>
              

...

 

...

 </AddLight>
            

...

 

...

 </FacetScript>
         

...

 

...

  </Invoke>
            

...

<Output 

...

Name="

...

Result" 

...

As="

...

ActionResult"

...

>
             

...

 

...

<Value>
         

...

     

...

 

 

...

titleQueries

...

Go to page

 

To subscribe to changes, use subscription is registered by through a query (query, create)

 

...

languagexml
titleSubscribe to temperature sensor
linenumberstrue

...

  <LoadLights>True</LoadLights>
              

...

</Value>
        

...

 

...

 

...

  </Output>
          

...

</Task>
        </

...

Workflow>
      </

...

Action>
    </

...

ThingFacet>

Let's combine PhilipLightManagerFacet with a PhilipLightManagerModel.

Code Block
languagexml
title

...

PhilipLightManagerModel
linenumberstrue

...

<Topic>Atomiton.Sensor.TempSensor.tempValue</Topic>
<Topic>Atomiton.Sensor.TempSensor.*</Topic>

The Label is the string that will be attached to every message you receive from this subscription. Here we give an sid to this instance of the subscription.

<ThingModel Name="PhilipLightManagerModel" Combines="PhilipLightManagerFacet">
      <Sid Name="ManagerId"/>
</ThingModel>

Query and subscription

Queries we need are:

  • Trigger Loading of Lights using PhilipLightManagerModel
  • Change the state of Light using PhilipLightModel
  • Find the Light and Manager models.

Queries

Code Block
languagexml
titleFind Lights
linenumberstrue
 <Query>
  <Find format="all">
    <PhilipLightModel>
      <LightNumber eq="1"/>
    </PhilipLightModel>
  </Find>
</Query>


Code Block
languagexml
titleGetLightManager
linenumberstrue
<Query>
  <Find format="All">
    <PhilipLightManagerModel>
      <ManagerId ne=""/>
    </PhilipLightManagerModel>
  </Find>
</Query>


Code Block
languagexml
titleInitManager
linenumberstrue
<Query>
  <DeleteAll>
    <PhilipLightManagerModel>
      <ManagerId ne=""/>
    </PhilipLightManagerModel>
  </DeleteAll>
  <Create>
    <PhilipLightManagerModel>
      <LoadLights>
        True
      </LoadLights>
    </PhilipLightManagerModel>
  </Create>
</Query>


Code Block
languagexml
titleToggleLight
linenumberstrue
<Query>
  <Find format="All">
    <PhilipLightModel>
      <LightNumber eq="1"/>
    </PhilipLightModel>
  </Find>
  <SetResponseData>
    <Key>
      Message.Value.Find.Result.PhilipLightModel.state.On.Value
    </Key>
    <Value>
      false
    </Value>
  </SetResponseData>
  <Update>
    <From>
      Result
    </From>
    <Include>
      $Response.Message.Value.Find
    </Include>
  </Update>
</Query>


Code Block
languagexml
title

...

PhilipLight Complete Model
linenumberstrue
collapsetrue
<Namespace Name="Atomiton

...

">
  <Domain Name="Lights">
    

...

<PhilipLightBaseURI>http://10.0.2.16/api/newdeveloper</PhilipLightBaseURI>
    <Def Name="PhilipLightState">
 

...

     <Boolean Name="On"/>
 

...

     <Integer Name="bri"/>
   

...

   <Integer Name="hue"/>
      

...

<Integer Name="sat"/>
      <String Name="effect"/>
   

...

   <Double Name="xy" cardinality="2"/>
      <Integer Name="ct"/>

...

      <String Name="alert"/>
      

...

<String Name="colormode"/>
      

...

<Boolean Name="reachable"/>
    </

...

Def>

    

...

<Macro Name="ExecuteQuery">
   

...

   <Argument>
      

...

  

...

<QueryString>
    

...

      

...

<Query/

...

>
        

...

</QueryString>
   

...

   </Argument>
      

...

<Result>
        <OnRequest>

...

          

...

<Target>[:RuntimeParams.FacetIDName:]</Target>
          

...

<Process>
         

...

   <Message>
    

...

        

...

  <Value>[:$Macro.Argument.QueryString:]</Value>
       

...

     </Message>
      

...

    </Process>
        </OnRequest>

...

      </Result>
    </Macro>

   

...

 <Macro Name="AddLight">
      <Argument>
        <LightNumber

...

/>
        <On/>
      

...

  <bri/>
        <hue/>
  

...

      <sat/>
      </Argument>

...

      <Result>
        <ExecuteQuery>

...

          <QueryString>
       

...

     <DeleteAll>
            

...

  <PhilipLightModel>
                <LightNumber 

...

Eq="[:$Macro.Argument.

...

LightNumber:]

...

"/>
              </PhilipLightModel>
            

...

</

...

DeleteAll>
            <Create>
           

...

   <PhilipLightModel>
                

...

<LightNumber>[:$Macro.Argument.

...

LightNumber:]</

...

LightNumber>
                <State>
  

...

                <On>[:$Macro.Argument.On:]</

...

On>
               

...

   <bri>[:$Macro.Argument.bri:]</bri>
        

...

          <hue>[:$Macro.Argument.hue:]</

...

hue>
       

...

      

...

     <sat>[:$Macro.Argument.sat:]</sat>
   

...

 

...

        

...

 

...

   </State>
    

...

 

...

        

...

 

...

</PhilipLightModel>
           

...

 

...

</Create>
         

...

 

...

</QueryString>
       

...

 </ExecuteQuery>
      </Result>
 

...

 

...

  </Macro>

    

...

<ThingFacet Name="

...

PhilipLightFacet"

...

>

...


      <String Name="

...

LightNumber"/>
      <PhilipLightState 

...

Name="State" KnownBy="

...

PhilipLightAction"/>

...


 

...

     

...

<String Name="

...

Type"/>

...


      <String 

...

Name="

...

modelid"/>
      

...

<String 

...

Name="

...

uniqueid"/>

...


      <String 

...

Name="

...

swversion"/>
      <!-- 

...

Helper Tags -->
      <AA>[:#o#Event.Argument:]</AA>
      

...

<Action 

...

Name="

...

PhilipLightAction" 

...

Documentation="

...

Set the state of the Light (true/false)">
       

...

 <Workflow Limit="1" Live="

...

1" 

...

Timeout="

...

-1"

...

>
          

...

<Task name="

...

Main" 

...

While="

...

True"

...

>
            

...

<Event name="

...

Argument" 

...

as="

...

ActionArgument"/>
     

...

       <Invoke 

...

Name="SetState" waitFor="ActionArgument" PUT="[:PhilipLightBaseURI:]/lights/[%:[:AA:].LightNumber.Value:%]/state">
    

...

          

...

<Message 

...

xmlns="

...

PLight" 

...

Type="

...

json"

...

>
       

...

 

...

        

...

<on_true>
        

...

 

...

        

...

 

...

<on>true</on>
        

...

 

...

       </on_true>

...

 

...

           

...

    <on_false>
   

...

        

...

       <on>false</on>
   

...

 

...

          

...

 

...

 </on_false>
            

...

 

...

 

...

  <Value>
           

...

 

...

 

...

     <Include>[:@WFRT:]on_[%:[:AA:].state.On.Value:%]</Include>
        

...

 

...

 

...

      </Value>
         

...

 

...

 

...

 

...

 

...

 </Message>
        

...

    </Invoke>
            <Output name="Result" as="ActionResult">

...


              <Value>
                

...

<State>
                  

...

<On>[%:[:AA:].state.On.Value:%]

...

</On>
                </

...

State>
              </Value>
            

...

</Output>

...


          </Task>

...


        </Workflow>
      

...

</Action>

...


    </ThingFacet>

...



    <ThingFacet Name="PhilipLightManagerFacet">

...


      <String Name="LoadLights" KnownBy="LoadLightsAction"/>
      

...

<Action Name="LoadLightsAction">

...


        <Workflow Limit="1" Live="1" Timeout="-1">

...


          <Task Name="Main" While="True">
            

...

<Event Name="Argument" 

...

As="ActionArgument"/>
            

...

<Invoke Name="GetLights" waitFor="ActionArgument" Get="[:PhilipLightBaseURI:]/lights"/>

...


            <Log Message="Lights Loaded...[:Invoke.GetLights.Message.Value:]"/>

...


            <Invoke Name="ParseGetLightsResult">
              

...

<FacetScript>

...


                <AddLight>

...


                  <LightNumber>1</LightNumber>
                  

...

<On>[:Invoke.GetLights.Message.Value.1.State.On:]</On>

...


                  <bri>[:Invoke.GetLights.Message.Value.1.State.bri:]</bri>

...


                  <hue>[:Invoke.GetLights.Message.Value.1.State.hue:]</hue>
                  

...

<sat>[:Invoke.GetLights.Message.Value.1.State.sat:]</sat>

...


                </AddLight>

...


                <AddLight>
                  

...

<LightNumber>2</LightNumber>

...


                  <On>[:Invoke.GetLights.Message.Value.2.State.On:]</On>

...


                  <bri>[:Invoke.GetLights.Message.Value.2.State.bri:]</bri>
                  

...

<hue>[:Invoke.GetLights.Message.Value.2.State.hue:]</hue>

...


                  <sat>[:Invoke.GetLights.Message.Value.2.State.sat:]</sat>

...


                </AddLight>
                

...

<AddLight>

...


                  <LightNumber>3</LightNumber>

...


                  <On>[:Invoke.GetLights.Message.Value.3.State.On:]</On>
                  

...

<bri>[:Invoke.GetLights.Message.Value.3.State.bri:]</bri>

...


                  <hue>[:Invoke.GetLights.Message.Value.3.State.hue:]</hue>

...


                  <sat>[:Invoke.GetLights.Message.Value.3.State.sat:]</sat>
                

...

</AddLight>

...


              </FacetScript>

...


            </Invoke>
            

...

<Output Name="Result" 

...

As="ActionResult">
              

...

<Value>

...


                <LoadLights>True</LoadLights>

...


              </Value>
            

...

</Output>

...


          </Task>

...


        </Workflow>
      

...

</Action>

...


    </ThingFacet>

...



    <ThingModel Name="PhilipLightModel" Combines="PhilipLightFacet">

...


      <Sid Name="LightId"/>
    

...

</ThingModel>

...



    

...

<ThingModel Name="PhilipLightManagerModel" Combines="PhilipLightManagerFacet">
      

...

<Sid Name="ManagerId"/>

...


    </ThingModel>

...


  </Domain>

...

</Namespace>

...