Skip to content

Commit

Permalink
feat(iotevents): support actions
Browse files Browse the repository at this point in the history
  • Loading branch information
yamatatsu committed Feb 8, 2022
1 parent ccc1988 commit d665d82
Show file tree
Hide file tree
Showing 8 changed files with 431 additions and 73 deletions.
196 changes: 171 additions & 25 deletions packages/@aws-cdk/aws-iotevents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,65 +40,211 @@ Import it into your code:
import * as iotevents from '@aws-cdk/aws-iotevents';
```

## `DetectorModel`
## Overview

The following example creates an AWS IoT Events detector model to your stack.
The detector model need a reference to at least one AWS IoT Events input.
AWS IoT Events inputs enable the detector to get MQTT payload values from IoT Core rules.
The following example is a minimal set of an AWS IoT Events detector model.
It has no feature but it maybe help you to understand overview.

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

// First, define the input of the detector model
const input = new iotevents.Input(this, 'MyInput', {
inputName: 'my_input', // optional
attributeJsonPaths: ['payload.deviceId', 'payload.temperature'],
});

const warmState = new iotevents.State({
// Second, define states of the detector model.
// You can define multiple states and its transitions.
const state = new iotevents.State({
stateName: 'warm',
onEnter: [{
eventName: 'test-event',
eventName: 'onEnter',
condition: iotevents.Expression.currentInput(input),
}],
});
const coldState = new iotevents.State({
stateName: 'cold',

// Finally, define the detector model.
new iotevents.DetectorModel(this, 'MyDetectorModel', {
initialState: state,
});
```

// transit to coldState when temperature is 10
warmState.transitionTo(coldState, {
Each part is explained in detail below.

## `Input`

You can create `Input` as following. You can put messages to the Input with AWS IoT Core Topic Rule, AWS IoT Analytics and more.
For more information, see [the documentation](https://docs.aws.amazon.com/iotevents/latest/developerguide/iotevents-getting-started.html).

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

const input = new iotevents.Input(this, 'MyInput', {
inputName: 'my_input', // optional
attributeJsonPaths: ['payload.deviceId', 'payload.temperature'],
});
```

To grant permissions to put messages in the input,
you can use the `grantWrite()` method:

```ts
import * as iam from '@aws-cdk/aws-iam';
import * as iotevents from '@aws-cdk/aws-iotevents';

declare const grantable: iam.IGrantable;
const input = iotevents.Input.fromInputName(this, 'MyInput', 'my_input');

input.grantWrite(grantable);
```

## `State`

You can create `State` as following.
In `onEnter` of a detector model's initial state, at least one reference of input via `condition` is needed.
And if the `condition` is evaluated to `TRUE`, the detector instance are created.
You can set the reference of input with `iotevents.Expression.currentInput()` or `iotevents.Expression.inputAttribute()` as following.
In other states, `onEnter` is optional.

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

declare const input: iotevents.IInput;

const initialState = new iotevents.State({
stateName: 'MyState',
onEnter: [{
eventName: 'onEnter',
condition: iotevents.Expression.currentInput(input),
}],
});
```

You can set actions to the `onEnter` event. It is caused if `condition` is evaluated to `TRUE`.
If you omit `condition`, actions is caused on every enter events of the state.
For more information, see [supported actions](https://docs.aws.amazon.com/iotevents/latest/developerguide/iotevents-supported-actions.html).

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

declare const input: iotevents.IInput;

const setTemperatureAction = {
bind: () => ({
configuration: {
setVariable: { variableName: 'temperature', value: temperatureAttr.evaluate() },
},
}),
};

const state = new iotevents.State({
stateName: 'MyState',
onEnter: [{ // optional
eventName: 'onEnter',
actions: [setTemperatureAction], // optional
condition: iotevents.Expression.eq(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('10'),
), // optional
}],
});
```

Also you can use `onInput` and `onExit`. `onInput` is triggered when messages are put to the input
that is refered from the detector model. `onExit` is triggered when exiting this state.

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

const state = new iotevents.State({
stateName: 'warm',
onEnter: [{ // optional
eventName: 'onEnter',
}],
onInput: [{ // optional
eventName: 'onInput',
}],
onExit: [{ // optional
eventName: 'onExit',
}],
});
```

You can set transitions of the states as following:

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

declare const input: iotevents.IInput;
declare const action: iotevents.IAction;
declare const stateA: iotevents.State;
declare const stateB: iotevents.State;

// transit from stateA to stateB when temperature is 10
stateA.transitionTo(stateB, {
eventName: 'to_coldState', // optional property, default by combining the names of the States
actions: [action], // optional,
when: iotevents.Expression.eq(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('10'),
),
});
// transit to warmState when temperature is 20
coldState.transitionTo(warmState, {
when: iotevents.Expression.eq(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('20'),
),
});
```

## `DetectorModel`

You can create `DetectorModel` as following.

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';

declare const state: iotevents.State;

new iotevents.DetectorModel(this, 'MyDetectorModel', {
detectorModelName: 'test-detector-model', // optional
description: 'test-detector-model-description', // optional property, default is none
evaluationMethod: iotevents.EventEvaluation.SERIAL, // optional property, default is iotevents.EventEvaluation.BATCH
detectorKey: 'payload.deviceId', // optional property, default is none and single detector instance will be created and all inputs will be routed to it
initialState: warmState,
initialState: state,
});
```

To grant permissions to put messages in the input,
you can use the `grantWrite()` method:
## Examples

The following example creates an AWS IoT Events detector model to your stack.
The State of this detector model transits according to the temperature.

```ts
import * as iam from '@aws-cdk/aws-iam';
import * as iotevents from '@aws-cdk/aws-iotevents';

declare const grantable: iam.IGrantable;
const input = iotevents.Input.fromInputName(this, 'MyInput', 'my_input');
const input = new iotevents.Input(this, 'MyInput', {
attributeJsonPaths: ['payload.deviceId', 'payload.temperature'],
});

input.grantWrite(grantable);
const warmState = new iotevents.State({
stateName: 'warm',
onEnter: [{
eventName: 'onEnter',
condition: iotevents.Expression.currentInput(input),
}],
});
const coldState = new iotevents.State({
stateName: 'cold',
});

const temperatureEqual = (temperature: string) =>
iotevents.Expression.eq(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('10'),
)

// transit to coldState when temperature is 10
warmState.transitionTo(coldState, { when: temperatureEqual('10') });
// transit to warmState when temperature is 20
coldState.transitionTo(warmState, { when: temperatureEqual('20') });

new iotevents.DetectorModel(this, 'MyDetectorModel', {
detectorKey: 'payload.deviceId',
initialState: warmState,
});
```
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-iotevents/lib/detector-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class DetectorModel extends Resource implements IDetectorModel {
key: props.detectorKey,
detectorModelDefinition: {
initialStateName: props.initialState.stateName,
states: props.initialState._collectStateJsons(new Set<State>()),
states: props.initialState.bind(this),
},
roleArn: role.roleArn,
});
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-iotevents/lib/event.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IAction } from './action';
import { Expression } from './expression';

/**
Expand All @@ -15,4 +16,11 @@ export interface Event {
* @default - none (the actions are always executed)
*/
readonly condition?: Expression;

/**
* The actions to be performed.
*
* @default - none
*/
readonly actions?: IAction[];
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-iotevents/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './action';
export * from './detector-model';
export * from './event';
export * from './expression';
Expand Down
Loading

0 comments on commit d665d82

Please sign in to comment.