Associate multiple thing actions

One can associate multiple actions to a Thingfacet Attribute. You can do this by providing comma separated list of Action names. For example:

Assoicating Multiple Actions
#
String(name: "State", KnownBy: "SyncImageAction,SyncPresetAction")


Here you can see two actions: SyncPresetAction and SyncImageActon which deal with camera preset and snapshot image respectively. Both the actions update the "State" attribute of a Camera Facet.


Multiple Thing Actions
# 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():%]
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':%]
          Image:
            [%:[%:@Output:%]/if([:IOK:]) then Invoke/GetImage/Message/Value/text() else '/img/no-image.jpg':%]


Rules for Selecting an Action:

TQLEngine Rules for selecting an Action are as follows. Please note that an Action is Triggered whenever there is a change detected between "Value" and "Known" values of a ThingFacet Attribute. A change is notified by Applications using TQL Update Query.

  • Order of Action Names specified in KnownBy - The first Action Name gets first preference, second gets second preference and so on.
  • Minimum number of Action (s) that satisfy the update criteria. This rule is used in conjunction with previous order of preference rule.


ESKY Camera Thing Facet
#
ThingFacet(Name: "Esky"): 
  Sid(Name: "CameraId")
  String(Name: "URL")
  String(Name: "UserName")
  String(Name: "Password")
  String(Name: "State", KnownBy: "SyncImageAction,SyncPresetAction")
  String(Name: "Image", KnownBy: "SyncImageAction")
  String(Name: "Preset", KnownBy: "SyncPresetAction")
  Unique(Name: "Camera", value: "URL")
  
  # Helpers
  AA:
    [:#o#Event.Argument:]
  UP:
    user=[%:[:AA:].UserName.Value:%][%:amp:%]pwd=[%:[:AA:].Password.Value:%]
  POK:
    Invoke/SetPreset/Message/starts-with(Value, 'ok')
  IOK:
    Invoke/GetImage/Message/starts-with(Value, 'data')
  
  #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':%]
            Preset:
              [%:[%:@Output:%]/if([:POK:]) then '[%:[:AA:].Preset.Value:%]' else null():%]
              
  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':%]
            Image:
              [%:[%:@Output:%]/if([:IOK:]) then Invoke/GetImage/Message/Value/text() else '/img/no-image.jpg':%]


For example in case of ESKY Camera Facet - here is the list the table of Attribute, Action Association and Attributes that get affected by Actions.

AttributeAction(s) AssociationAttribute(s) Being Updated By Action
StateSyncImageAction, SyncPresetActionState, Image, Preset
Image
SyncImageActionState, Image
PresetSyncPresetActionState, Preset


Based on the above Action Association and Rules applied by the TQLEngine, table below gives possibilities:

User's (Applications) Desire to update using TQL Update QueryAction Selected by TQLEngine
ImageSyncImageAction
PresetSyncPresetAction
Image, State
SyncImageAction
State
SyncImageAction (* Note both Rules get applied)