Versions Compared

Key

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

...

Action steps can be classified into as definition and execute phase.

Image RemovedImage Added

Action Definition

...

Code Block
languagexml
titlePreset Camera
linenumberstrue
collapsetrue
<Action name="SyncPresetAction" documentation="Synchronize camera state and preset">
  <Workflow Limit="1" Live="1" Timeout="PT20S">
    <Task name="Main" while="true">
      <Event name="Argument" as="ActionArgument"/>
      <Invoke name="SetPreset" waitFor="Argument" skip-if="[%:[:AD:].Preset/no-value(Value):%]" delayAfter="PT5S"
        get="[%:[:AA:].URL.Value:%]/cgi-bin/decoder_control.cgi?[:UP:][%:amp:%]command=15[%:amp:%]sit=[%:[:AD:].Preset.Value:%]"/>
      <Output name="Result" as="ActionResult">
        <Value>
          <State> [%:[%:@Output:%]/if([:POK:]) then 'ON' else 'OFF':%]</State>
          <Preset>[%:[%:@Output:%]/if([:POK:]) then '[%:[:AD:].Preset.Value:%]' else null():%]</Preset>
        </Value>
      </Output>
    </Task>
  </Workflow>
</Action>
Code Block
languagexml
titleTake Picture From a Camera
linenumberstrue
collapsetrue
<Action name="TakePictureAction" documentation="Synchronize camera state and snapshot image">
  <Workflow Limit="1" Live="1" Timeout="PT10S">
    <Task name="Main" while="true">
      <Event name="Argument" as="ActionArgument"/>
      <Invoke name="GetImage" waitFor="Argument" delay="PT1S" get="[%:[:AA:].URL.Value:%]/cgi-bin/video_snapshot.cgi?[:UP:]"/>
      <Output name="Result" as="ActionResult">
        <Value>
          <State>[%:[%:@Output:%]/if([:IOK:]) then 'ON' else 'OFF':%]</State>
          <Image>[%:[%:@Output:%]/if([:IOK:]) then Invoke/GetImage/Message/Value/text() else '/img/no-image.jpg':%]</Image>
        </Value>
      </Output>
    </Task>
  </Workflow>
</Action>

 

In case of AppFacet an Action represents:

...

Code Block
languagexml
titleSend an Email
linenumberstrue
collapsetrue
<Action name="EmailAction" documentation="Send Email">
  <Workflow Limit="1" Live="1" Timeout="0">
    <Task name="Main" while="true">
      <Event name="Argument" as="ActionArgument"/>
      <Invoke name="ReadValue" waitFor="Argument" post="smtp://[%:Event.Argument.Hostname.Value:%]" Hostname="[%:Event.Argument.Hostname.Value:%]">
        <Message>
          <Value>
            <Port>[%:Event.Argument.Port.Value:%]</Port>
            <Username>[%:Event.Argument.Username.Value:%]</Username>
            <Password>[%:Event.Argument.Password.Value:%]</Password>
            <From>[%:Event.Argument.From.Value:%]</From>
            <To>[%:Event.Argument.To.Value:%]</To>
            <CC>[%:Event.Argument.CC.Value:%]</CC>
            <Subject>[%:Event.Argument.Subject.Value:%]</Subject>
            <Body>[%:Event.Argument.Body.Value:%]</Body>
            <StartTLS>[%:Event.Argument.StartTLS.Value:%]</StartTLS>
          </Value>
        </Message>
      </Invoke>
    </Task>
  </Workflow>
</Action>

...

Code Block
languagexml
titleStart Simulation by Executing External Script
linenumberstrue
collapsetrue
<Action Name="StartSimulatorAction" Documentation="Start the simulator">
  <Workflow Limit="1" Live="1" Timeout="-1">
    <Task name="Main">
      <StartOsWindows>StartProcess.exe cmd.exe "/K c:\Users\Dev\Documents\atomiton\bitbucket\tqlsimulator\build\install\TQLSimulator\bin\TQLSimulator.bat local
        -runAsFleetEventsGen eventOptions=10"</StartOsWindows>
      <StartOsUnix>bash config/startupscript.sh</StartOsUnix>
      <StartOsMac>[:CmdOsUnix:]</StartOsMac>
      <StopOsWindows>TaskKill.exe /PID [%:Output.ActionArgument.currentSimulatorState/Known/text():%]</StopOsWindows>
      <StopOsUnix>kill [%:Output.ActionArgument.currentSimulatorState/Known/text():%]</StopOsUnix>
      <StopOsMac>[:CmdOsUnix:]</StopOsMac>
      <Event name="Argument" as="ActionArgument"/>
      <Invoke name="InvokeScript" waitFor="ActionArgument" skip-if="[%:Output.ActionArgument.currentSimulatorState/starts-with(Value, 'off'):%]"
        execute="[:Start[:OsTag:]:]">
      </Invoke>
      <Output name="ActionResult">
        <Value>
          <currentSimulatorState>
            [%:Invoke/InvokeScript/Message/Value/text():%]
          </currentSimulatorState>
        </Value>
      </Output>
    </Task>
  </Workflow>
</Action>

...

An Action must be associated or attached to a Model Facet Attribute. This association varies depending on where an Action is defined. Please refer to <subscribe> and <sequence> for their respective action associations.

In case of ThingFacet or AppFacet, an Action is associated with an attribute of ThingFacet or AppFacet using the "KnownBy" Modifier modifier as below.

Code Block
languagexml
titleAction Named Element
linenumberstrue
<Double Name="RotateValue" KnownBy="RotateCameraAction"/>

...

Code Block
languagexml
titleMultiple Thing Actions
linenumberstrue
collapsetrue
<!-- Actions -->
<Action Name="SyncPresetAction" Documentation="Synchronize camera state and preset">
  <Workflow Limit="1" Live="1" Timeout="PT20S">
    <Task Name="Main" While="true">
      <Event Name="Argument" As="ActionArgument"/>
      <Invoke Name="SetPreset" waitFor="Argument" skip-if="[%:[:AA:].Preset/no-value(Value):%]" delayAfter="PT5S"
        get="[%:[:AA:].URL.Value:%]/cgi-bin/decoder_control.cgi?[:UP:][%:amp:%]command=15[%:amp:%]sit=[%:[:AA:].Preset.Value:%]"/>
      <Output name="Result" as="ActionResult">
        <Value>
          <State> [%:[%:@Output:%]/if([:POK:]) then 'ON' else 'OFF':%]</State>
          <Preset>[%:[%:@Output:%]/if([:POK:]) then '[%:[:AA:].Preset.Value:%]' else null():%]</Preset>
        </Value>
      </Output>
    </Task>
  </Workflow>
</Action>
<Action name="SyncImageAction" documentation="Synchronize camera state and snapshot image">
  <Workflow Limit="1" Live="1" Timeout="PT10S">
    <Task name="Main" while="true">
      <Event name="Argument" as="ActionArgument"/>
      <Invoke name="GetImage" waitFor="Argument" delay="PT1S" get="[%:[:AA:].URL.Value:%]/cgi-bin/video_snapshot.cgi?[:UP:]"/>
      <Output name="Result" as="ActionResult">
        <Value>
          <State>[%:[%:@Output:%]/if([:IOK:]) then 'ON' else 'OFF':%]</State>
          <Image>[%:[%:@Output:%]/if([:IOK:]) then Invoke/GetImage/Message/Value/text() else '/img/no-image.jpg':%]</Image>
        </Value>
      </Output>
    </Task>
  </Workflow>
</Action>

...

In case when multiple attributes are updated, the system will select minimum number of actions with highest preference to perform the update[s]. That is, if only state needs to be updated, the engine will use SyncImageAction action and when both state and preset need updates, SyncPresetAction will be used.

Action Results in

...

the change of Attribute's "Known" Value:

From the action, using the output of the workflow, you can update any attributes of the ThingFacet of AppFacet. It is always the "Known" value of the attribute that will be updated. In this example, Action is changing State and Image Attributes.

Code Block
languagexml
titleAction Result
linenumberstrue
collapsetrue
<Output name="Result" as="ActionResult">
  <Value>
    <State>[%:[%:@Output:%]/if([:IOK:]) then 'ON' else 'OFF':%]</State>
    <Image>[%:[%:@Output:%]/if([:IOK:]) then Invoke/GetImage/Message/Value/text() else '/img/no-image.jpg':%]</Image>
  </Value>
</Output>

...

Trigger is an execution phase of an Action. Execution of an Action is asynchronous and can be triggered in any number of ways. Please refer to to <subscribe> and <sequence> for their respective action triggers.

...

Code Block
languagexml
titleInstantiate a Device using TQL Query
linenumberstrue
collapsetrue
<Query>
  <Save format="version,current">
    <RfidReader ReaderId="R1" URL="perif://">
        <RFID value="$Null()" version="1"/>
    </RfidReader>
  </Save>
</Query>

 

Automatic Action Trigger

In case of certain devices - like sensors which send data continuously, one can set the trigger of action  execution to happen automatically using update="auto" attribute at the time of Action association. For example:

...

Code Block
languagexml
titleAutomatic Action Example
linenumberstrue
collapsetrue
<Action name="RFIDReaderAction" documentation="Read RFID tag and update the instance">
  <Workflow Limit="1" Live="1" Timeout="-1">
    <Task name="Main" while="true">
      <Event name="Argument" as="ActionArgument"/>
      <Invoke name="ReadId" waitFor="Argument" get="[%:Event.Argument.URL.Value:%]"/>
      <Output name="Result" as="ActionResult">
        <Value>
          <RFID>[%:[%:@Output:%]Invoke.ReadId.Message.Value:%]</RFID>
        </Value>
      </Output>
    </Task>
  </Workflow>
</Action>

 

For example, if you initiate an RFID reader in standard fashion, it will wait for ONE reader event, update the known value of its model instance and stop. You’ll need to update its instance again to make it wait for the next event and so on. Update=”auto” allows to automate such workflow re-activation. Every time it processes an event, thing workflow will automatically restart itself to be ready for the next device event. This way you can have a continuous stream of events from the device without explicit request/re-activation after each one.

...