コマンドを実行するトリガー

コマンドを自動実行する場合、実行するコマンドのテンプレートと実行条件をトリガーに設定します。以下に例を示します。

時間条件(単発)のトリガーの登録

単発の時間条件を持つトリガーとして、「今から 1 時間後に、エアコンをオンにする(設定温度 25 度、ファンスピード 5)」というトリガーを登録する例を以下に示します。

// Create a command.
var actions = [Dictionary<String, AnyObject>]()
let action1: Dictionary<String, AnyObject> = ["turnPower": ["power": true]]
let action2: Dictionary<String, AnyObject> = ["setPresetTemperature": ["presetTemperature": 25]]
let action3: Dictionary<String, AnyObject> = ["setFanSpeed": ["fanSpeed": 5]]
actions.append(action1)
actions.append(action2)
actions.append(action3)

// Create a predicate.
// Execute the command in an hour.
let scheduleAt = NSDate(timeIntervalSinceNow: 60*60)
let predicate = ScheduleOncePredicate(scheduleAt: scheduleAt)

// Send a trigger.
api.postNewTrigger("AirConditioner-Demo", schemaVersion: 1, actions: actions, predicate: predicate, completionHandler: { (trigger: Trigger?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

ここでは以下の処理が行われています。

  • [Dictionary<String, AnyObject>] に、トリガーによって実行されるコマンドを作成します。ここでは、3 つのアクションを順番に設定しています。設定方法は コマンドの実行 のコードと同じです。

  • scheduleAt にトリガーの実行時間を設定し、ScheduleOncePredicate の引数とします。

  • 最終的に、postNewTrigger メソッドでトリガーを登録します。

Thing Interaction Framework がトリガーを受け付けた段階でコールバックメソッドが呼び出されます。

時間条件(繰り返し)のトリガーの登録

繰り返しの時間条件を持つトリガーとして、「毎日午前 9 時に、エアコンをオンにする(設定温度 25 度、ファンスピード 5)」というトリガーを登録する例を以下に示します。

// Create a command.
var actions = [Dictionary<String, AnyObject>]()
let action1: Dictionary<String, AnyObject> = ["turnPower": ["power": true]]
let action2: Dictionary<String, AnyObject> = ["setPresetTemperature": ["presetTemperature": 25]]
let action3: Dictionary<String, AnyObject> = ["setFanSpeed": ["fanSpeed": 5]]
actions.append(action1)
actions.append(action2)
actions.append(action3)

// Create a predicate.
// Execute the command at 9:00 a.m. every day.
let predicate = SchedulePredicate(schedule: "0 9 * * *")

// Send a trigger.
api.postNewTrigger("AirConditioner-Demo", schemaVersion: 1, actions: actions, predicate: predicate, completionHandler: { (trigger: Trigger?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

基本的な流れは、単発の時間条件の場合と同じですが、トリガーの実行条件の初期化方法が異なります。

  • schedule にトリガーの実行時間を設定し、SchedulePredicate の引数とします。設定方法については、時間条件(繰り返し) を参照してください。

ステート条件のトリガーの登録

単純なステート条件を持つトリガーとして、「室温が 30 度以上の時、エアコンをオンにする(設定温度 25 度、ファンスピード 5)」というトリガーを登録する例を以下に示します。

// Create a command.
var actions = [Dictionary<String, AnyObject>]()
let action1: Dictionary<String, AnyObject> = ["turnPower": ["power": true]]
let action2: Dictionary<String, AnyObject> = ["setPresetTemperature": ["presetTemperature": 25]]
let action3: Dictionary<String, AnyObject> = ["setFanSpeed": ["fanSpeed": 5]]
actions.append(action1)
actions.append(action2)
actions.append(action3)

// Create a predicate.
// Execute the command when the temperature is greater than or equal to 30 deg C.
let condition = Condition(clause:RangeClause(field: "currentTemperature", lowerLimit: 30, lowerIncluded: true))
let predicate = StatePredicate(condition: condition, triggersWhen: TriggersWhen.CONDITION_FALSE_TO_TRUE)

// Send a trigger.
api.postNewTrigger("AirConditioner-Demo", schemaVersion: 1, actions: actions, predicate: predicate, completionHandler: { (trigger: Trigger?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

基本的な流れは、時間条件の場合と同じですが、トリガーの実行条件の初期化方法が異なります。

  • トリガーの条件を作成します。まず、Condition に比較条件を設定します。ここでは、ステート で登録している currentTemperature が 30 以上の場合に true になる条件を作成しています。
  • 次に、StatePredicate を作成します。StatePredicate が最終的にトリガーに登録する条件です。コマンドは、30 度未満の状態から 30 度以上になったときに実行したいため、CONDITION_FALSE_TO_TRUE を指定します。

複数のステート条件での登録例

ステート条件を AND で結合する例を以下に示します。この例では、「電源がオン」かつ「湿度が 80 より大きい」場合に「ファンスピードを 10 に設定する」というトリガーを登録します。

// Create a command.
let actions: [Dictionary<String, AnyObject>] = [["setFanSpeed": ["fanSpeed": 10]]]

// Create a predicate.
// Execute the command when the power is on and the humidity is greater than 80%.
let condition = Condition(clause:
            AndClause(clauses:EqualsClause(field: "power", boolValue: true),
                              RangeClause(field: "currentHumidity", lowerLimitInt: 80, lowerIncluded: false)))
let predicate = StatePredicate(condition: condition, triggersWhen: TriggersWhen.CONDITION_FALSE_TO_TRUE)

// Send a trigger.
api.postNewTrigger("AirConditioner-Demo", schemaVersion: 1, actions: actions, predicate: predicate, completionHandler: { (trigger: Trigger?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

基本的な流れは、単一のステート条件の場合と同じですが、Condition の初期化方法が異なります。ここでは、「power が true に等しい」という条件と、「currentHumidity が 80 より大きい」という 2 つの条件を作成し、それを And で結合したものを比較条件として設定しています。

詳細情報を指定したトリガーの登録例

トリガーを設定する際、詳細情報を指定することで、以下のようなトリガーを登録することができます。

  • 他の Thing にコマンドを送信

    ある Thing でステート条件が満たされたとき、別の Thing にコマンドを送信するようなトリガーを登録できます。

    例えば、温度計デバイスとエアコンが別の Thing として管理されているとき、「温度計デバイスが一定の温度以上になったとき、エアコンの電源を入れる」というようなトリガーを実現できます。

  • コマンドやトリガーの詳細情報を設定

    コマンドとトリガーのそれぞれに対して、タイトル、詳細な説明文、JSON 形式で表現された任意のメタ情報を設定できます。

// Create a command.
var actions = [Dictionary<String, AnyObject>]()
let action1: Dictionary<String, AnyObject> = ["turnPower": ["power": true]]
let action2: Dictionary<String, AnyObject> = ["setPresetTemperature": ["presetTemperature": 25]]
let action3: Dictionary<String, AnyObject> = ["setFanSpeed": ["fanSpeed": 5]]
actions.append(action1)
actions.append(action2)
actions.append(action3)

// Get the target thing that receives the command.
let target = api2.target
let targetID = target.getTypedID()

// Create a command form from detailed information.
let metadataCommand: Dictionary<String, AnyObject> = ["iconIndex":3, "issuer":"trigger"]
let form = TriggeredCommandForm(schemaName: "AirConditioner-Demo", schemaVersion: 1, actions: actions, targetID: targetID, title: "Power on", commandDescription: "Power on and set to 25 deg C", metadata: metadataCommand)

// Create a predicate.
let condition = Condition(clause:RangeClause(field: "currentTemperature", lowerLimit: 30, lowerIncluded: true))
let predicate = StatePredicate(condition: condition, triggersWhen: TriggersWhen.CONDITION_FALSE_TO_TRUE)

// Create trigger options from detailed information.
let metadataTrigger: Dictionary<String, AnyObject> = ["createdBy":"Alice"]
let options = TriggerOptions(title: "Power on", triggerDescription: "Power on when the temperature goes over 30 deg C", metadata: metadataTrigger)

// Send a trigger.
api.postNewTrigger(form: form, predicate: predicate, options: options, completionHandler: { (trigger: Trigger?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

ここでは、次の処理を行っています。

  • 条件が満たされた場合に実行されるアクションを actions に用意します。

  • 実行するコマンドの詳細を TriggeredCommandForm に設定します。

    • targetID でコマンドの送信先の Thing を指定します。
      このサンプルコードでは、ThingIFAPI インスタンスの apiapi2 によって、それぞれ温度計デバイスとエアコンの Thing が管理されているものとします。api(温度計)のステートが指定条件を満たした場合、api2(エアコン)から取得した target に対してエアコンの電源を入れるコマンドを実行します。
      apiapi2 は、それぞれでインスタンス生成や初期登録処理が実行されており、同一のオーナーであることが必要です。
      なお、targetID を省略した場合は postNewTrigger を実行した ThingIFAPI に設定されている Thing にコマンドを送信します。
    • titlecommandDescriptionmetadata によって詳細情報を設定できます。
      これらは コマンドの詳細情報 に示すとおり、アプリケーションの仕様に合わせて自由に利用できます。最大長などの制限値についても コマンドの詳細情報 をご覧ください。
  • 実行する条件を StatePredicate として作成します。

  • トリガーに対する詳細情報を TriggerOptions に設定します。コマンドと同様、アプリケーション独自の情報を設定できます。最大長などの制限値はコマンドに対する詳細情報と同じです。

  • 最後に、作成した TriggeredCommandFormStatePredicateTriggerOptionspostNewTrigger メソッドに指定して、新しいトリガーを登録します。