ThingFacet Camera Example

Here you can see two actions: SyncPreset and SyncImage which deal with camera preset and snapshot image respectively. Both also update camera state.

In order to tell the system how to select actions, a new attribute “KnownBy” is added. It contains a list of all actions which can update given attribute in order of preference (e.g. based on action performance, execution time etc., for example). 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 SyncImage action and when both state and preset need updates, SyncPreset will be used.

·         A number of improvements has been introduced to workflow definition language:

o   delayAfter parameter allows to delay process execution after enclosing invoke was completed. This allows to avoid extra invokes for pure waiting. In the example above, the WF gives camera 5 seconds to process the preset change (i.e. rotate the camera to new preset position). This allows to encapsulate the whole preset change thing into a single invoke.

o   OnlyIf (also recognized as only-if) invoke parameter is a negative to already existing skip-if. That is only-if === not(skip-if) and vice versa. The invoke will be executed when only-if condition is true. This is for convenience.

·         As per request, OldValue and OldKnown have been added to the subscription messages. They contain previous values of value and known respectively.


ThingFacet Camera Example
#
ThingFacet(name: "Esky"):
      Sid(name: "CameraId")
      String(name: "URL")
      String(name: "UserName")
      String(name: "Password")
      String(name: "State", KnownBy: "SyncImage,SyncPreset")
      String(name: "Image", KnownBy: "SyncImage")
      String(name: "Preset", KnownBy: "SyncPreset")
      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: "SyncPreset", 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: "SyncImage", 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':%]