# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.


---
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS template for SiteWise demo
Outputs:
  StackArn:
    Value: {Ref: 'AWS::StackId'}
  SiteWiseAsset1Id: 
    Description: The AssetId for Asset 1 in AWS IoT SiteWise, Data Scientists use this for L4E model 
    Value:
      Ref: IoTSiteWiseDemoPumpAsset1
  SiteWiseAsset2Id:
    Description: The AssetId for Asset 2 in AWS IoT SiteWise, Data Scientists use this for L4E model
    Value:
      Ref: IoTSiteWiseDemoPumpAsset2  
Parameters:
  DemoDurationDays:
    Type: Number
    Default: 7
    AllowedValues: [2, 3, 4, 5, 6, 7, 14]  
  FirstPropertyGroup:
    Type: String
    Description: The list of property names
    Default: Sensor0 Sensor1 Sensor2 Sensor3 Sensor4 Sensor5
  SecondPropertyGroup:
    Type: String
    Description: The list of property names
    Default:  Sensor6 Sensor7 Sensor8 Sensor9 Sensor10 Sensor11 
  ThirdPropertyGroup:
    Type: String
    Description: The list of property names
    Default:  Sensor12 Sensor13 Sensor14 Sensor15 Sensor16 Sensor17
  FourthPropertyGroup:
    Type: String
    Description: The list of property names
    Default:  Sensor18 Sensor19 Sensor20 Sensor21 Sensor22 Sensor23 
  FifthPropertyGroup:
    Type: String
    Description: The list of property names
    Default: Sensor24 Sensor25 Sensor26 Sensor27 Sensor28 Sensor29         
Conditions:
  # SiteWise (and our lambda bucket) only exists in these regions
  ValidRegion:
    Fn::Or:
    - Fn::Equals:
      - Ref: AWS::Region
      - us-east-1
    - Fn::Equals:
      - Ref: AWS::Region
      - us-west-2
    - Fn::Equals:
      - Ref: AWS::Region
      - eu-west-1
    - Fn::Equals:
      - Ref: AWS::Region
      - eu-central-1
    - Fn::Equals:
      - Ref: AWS::Region
      - ap-southeast-1
    - Fn::Equals:
      - Ref: AWS::Region
      - ap-southeast-2
    - Fn::Equals:
      - Ref: AWS::Region
      - cn-north-1
Resources:
  # IoT Events Alarm Models
  IoTSiteWiseDemoSiteWiseSubscriptionRole:
    Type: AWS::IAM::Role
    Condition: ValidRegion
    Properties:
      Path: "/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - iotsitewise.amazonaws.com
      Policies:
        - PolicyName: IotEventBatchPutMessageAccessPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - iotevents:BatchPutMessage
                Resource: "*"

  IoTSiteWiseDemoIotEventsActionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      Path: "/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - iotevents.amazonaws.com
                - iot.amazonaws.com
      Policies:
        - PolicyName: IoTSiteWiseDemoIoTEventsAllowPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - iotsitewise:BatchPutAssetPropertyValue
                  - sns:Publish
                  - firehose:PutRecord
                  - lambda:InvokeFunction
                  - sqs:SendMessage
                  - firehose:PutRecordBatch
                  - iot:Publish
                  - iotevents:DescribeLoggingOptions
                  - iotevents:ListDetectorModels
                  - iotevents:PutLoggingOptions
                  - iotevents:ListInputs
                  - sso-directory:DescribeUser
                Resource: "*"

  IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction:
    Type: AWS::Lambda::Function
    Condition: ValidRegion
    Properties:
      Description: IoT SiteWise Demo function handling the lifecycle of IoTEvents Alarm Model resources. This function will be deleted at the end of the demo.
      Code:
        S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region}
        S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip
      Handler: iotevents_alarm_models.handler
      MemorySize: 128
      Role:
        Fn::GetAtt: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole, Arn]
      Runtime: python3.7
      Timeout: 900

  IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole:
    Type: AWS::IAM::Role
    Condition: ValidRegion
    Properties:
      Description: Role for IoT SiteWise Demo IoTEvents Alarm Model resources lifecycle. This role will be deleted at the end of the demo.
      AssumeRolePolicyDocument:
        Statement:
          - Action:
            - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
        Version: '2012-10-17'
      Policies:
      - PolicyName: IoTSiteWiseDemo-IoTEventsAlarmModelLifecycleFunction-RolePolicy
        PolicyDocument:
          Statement:
            # CloudWatch logging
            - Action:
              - logs:CreateLogStream
              - logs:PutLogEvents
              - logs:CreateLogGroup
              Effect: Allow
              Resource:
                Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
            - Action:
              - logs:CreateLogStream
              - logs:PutLogEvents
              - logs:CreateLogGroup
              Effect: Deny
              NotResource:
                Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
            # SiteWise & IoT Events & pass role
            - Action:
              - iotsitewise:UpdateAssetModel
              - iotsitewise:DescribeAssetModel
              - iotsitewise:UpdateSubscription
              - iotsitewise:UpdateAssetModelPropertyRouting
              - iotevents:CreateAlarmModel
              - iotevents:DeleteAlarmModel
              - iotevents:DescribeAlarmModel
              - iotevents:updateAlarmModel
              - iam:PassRole
              Effect: Allow
              Resource: "*"
          Version: '2012-10-17'

  IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DependsOn:
     - IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction
     - IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole
    Condition: ValidRegion
    Properties:
      LogGroupName:
        Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction}"

  IoTSiteWiseDemoPumpL4EAlarmModel:
    Type: Custom::IoTSiteWiseDemoPumpL4EAlarmModel
    DependsOn: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole, IoTSiteWiseDemoSiteWiseSubscriptionRole, IoTSiteWiseDemoIotEventsActionExecutionRole, IoTSiteWiseDemoPumpAssetModel, IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionLogGroup]
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction, Arn]
      name: DemoPumpL4EAlarmModel
      description: SiteWise Demo Alarm model for L4E alarm. It will be deleted at the end of the demo.
      assetModelId: { Ref: IoTSiteWiseDemoPumpAssetModel }
      assetModelCompositeModelName: l4eAlarm
      roleArn:
        Fn::GetAtt: [IoTSiteWiseDemoIotEventsActionExecutionRole, Arn]
      sitewiseSubscriptionArn:
        Fn::GetAtt: [IoTSiteWiseDemoSiteWiseSubscriptionRole, Arn]
      severity: 1
      alarmRule: {
        simpleRule: {
          inputProperty: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, AVG L4E Score id] },
          comparisonOperator: GREATER_OR_EQUAL,
          threshold: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, L4E Alarm Threshold id] },
        }
      }
      alarmCapabilities: {
        initializationConfiguration: {
          disabledOnInitialization: false
        },
        acknowledgeFlow: {
          enabled: false
        }
      }
      alarmEventActions: {
        alarmActions: [
          {
            iotSiteWise: {
              assetId: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, AVG L4E Score id] },
              propertyId: lambda function will find alarm state property by composite model name
            }
          }
        ]
      }

  IoTSiteWiseDemoStationAbnormalyAlarmModel:
    Type: Custom::IoTSiteWiseDemoStationAbnormalyAlarmModel
    DependsOn: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionRole, IoTSiteWiseDemoSiteWiseSubscriptionRole, IoTSiteWiseDemoIotEventsActionExecutionRole, IoTSiteWiseDemoPumpStationAssetModel, IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunctionLogGroup]
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoIoTEventsAlarmModelLifecycleFunction, Arn]
      name: DemoStationAbnormalyAlarmModel
      description: SiteWise Demo Alarm model for station abnormaly alarm. It will be deleted at the end of the demo.
      assetModelId: { Ref: IoTSiteWiseDemoPumpStationAssetModel }
      assetModelCompositeModelName: StationAbnormalyAlarm
      roleArn:
        Fn::GetAtt: [IoTSiteWiseDemoIotEventsActionExecutionRole, Arn]
      sitewiseSubscriptionArn:
        Fn::GetAtt: [IoTSiteWiseDemoSiteWiseSubscriptionRole, Arn]
      severity: 1
      alarmRule: {
        simpleRule: {
          inputProperty: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpStationAssetModel, Total L4E Score id] },
          comparisonOperator: GREATER_OR_EQUAL,
          threshold: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpStationAssetModel, Station Abnormaly Threshold id] },
        }
      }
      alarmCapabilities: {
        initializationConfiguration: {
          disabledOnInitialization: false
        },
        acknowledgeFlow: {
          enabled: true
        }
      }
      alarmEventActions: {
        alarmActions: [
        {
          iotSiteWise: {
            assetId: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpStationAssetModel, Total L4E Score id] },
            propertyId: lambda function will find alarm state property by composite model name
          }
        }
        ]
      }

  # Asset Models
  IoTSiteWiseDemoAssetModelLifecycleFunction:
    Type: AWS::Lambda::Function
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: IoT SiteWise Demo function handling the lifecycle of asset model resources. This function will be deleted at the end of the demo.
      Code:
        S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region}
        S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip
      Handler: sitewise_asset_models.handler
      MemorySize: 128
      Role:
        Fn::GetAtt: [IoTSiteWiseDemoAssetModelLifecycleFunctionRole, Arn]
      Runtime: python3.7
      Timeout: 900

  IoTSiteWiseDemoAssetModelLifecycleFunctionRole:
    Type: AWS::IAM::Role
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Role for IoT SiteWise Demo asset model lifecycle. This role will be deleted at the end of the demo.
      AssumeRolePolicyDocument:
        Statement:
        - Action: ['sts:AssumeRole']
          Effect: Allow
          Principal:
            Service: [lambda.amazonaws.com]
        Version: '2012-10-17'
      Policies:
      - PolicyName: IoTSiteWiseDemo-AssetModelLifecycleFunction-RolePolicy
        PolicyDocument:
          Statement:
          # CloudWatch logging
          - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup']
            Effect: Allow
            Resource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
          - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup']
            Effect: Deny
            NotResource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
          # SiteWise
          - Action: ['iotsitewise:CreateAssetModel','iotsitewise:DescribeAssetModel','iotsitewise:DeleteAssetModel', 'iotsitewise:UpdateAssetProperty']
            Effect: Allow
            Resource: "*"
          Version: '2012-10-17'

  IoTSiteWiseDemoAssetModelLifecycleFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DependsOn: [IoTSiteWiseDemoAssetModelLifecycleFunction, IoTSiteWiseDemoDataGenerationFunctionRole]
    Condition: ValidRegion
    Properties:
      LogGroupName:
        Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoAssetModelLifecycleFunction}"

  IoTSiteWiseDemoPumpAssetModel:
    Type: Custom::IoTSiteWiseDemoPumpAssetModel
    DependsOn: [IoTSiteWiseDemoAssetModelLifecycleFunctionLogGroup, IoTSiteWiseDemoDataGenerationFunctionRole]
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoAssetModelLifecycleFunction, Arn]
      # These sitewise properties id will be available as attributes using Fn::GetAtt after asset model creation
      # For example, given metadata_sitewise_property_ids: [ Average Power, Overdrive State Time]
      #   Fn::GetAtt: [IoTSiteWiseDemoPumpAssetModel, Average Power id] returns the id of the property named Average Power
      # Note:
      #   A property must have the name field in order to be used as a metadata_sitewise_property_ids
      #   This will only work on top level properties with string values
      metadata_sitewise_property_ids:
        [
          L4E Alarm Threshold,
          Asset L4E Score,
          AVG L4E Score,
        ]
      name: Demo Pump Asset Model
      description: This is an asset model used in the IoT SiteWise Demo for representing a turbine in a wind farm. It will be deleted at the end of the demo.
      properties:
        [
          # Attributes
          { 
            name: Make, 
            dataType: STRING, 
            type: { attribute: { defaultValue: Amazon } }
          },
          {
            name: Model,
            dataType: INTEGER,
            type: { attribute: { defaultValue: 500 } } 
          },
          { 
            name: Location, 
            dataType: STRING, 
            type: { attribute: { defaultValue: Renton } } 
          },
          {
            name: L4E Alarm Threshold,
            dataType: DOUBLE,
            type: { attribute: { defaultValue: 0.9 } }
          },
          # Measurements
          {
            name: Sensor0, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor1,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor2,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor3,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor4,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor5,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor6,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor7,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor8,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor9,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor10,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor11,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor12,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor13,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor14,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor15,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor16,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor17,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor18,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor19,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor20,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor21,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor22,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor23,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor24,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor25,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor26,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor27,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor28,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor29,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor0 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor1 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor2 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor3 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor4 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor5 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor6 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor7 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor8 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor9 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor10 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor11 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor12 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor13 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor14 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor15 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor16 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor17 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor18 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor19 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor20 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor21 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor22 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor23 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor24 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor25 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor26 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor27 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor28 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Sensor29 L4EScore, 
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          {
            name: Asset L4E Score,
            dataType: DOUBLE,
            unit: NA,
            type: { measurement: {} }
          },
          #metric
          {
            name: AVG L4E Score,
            dataType: DOUBLE,
            unit: NA,
            type: { 
              metric: {
                expression: avg(l4e_score),
                variables: [
                  {
                    name: l4e_score,
                    value: { propertyId: Asset L4E Score }
                  }
                ],
                window: { tumbling: { interval: 5m } }
              }
            }
          }
        ]
      hierarchies:
        [
          # optional, added for simplicity in lambda (not requiring to have a special case for with/without hierarchies)
        ]
      assetModelCompositeModels:
        [
          {
            name: l4eAlarm,
            type: AWS/ALARM,
            properties:
              [
                {
                  name: AWS/ALARM_TYPE,
                  dataType: STRING,
                  unit: none,
                  type: {
                    attribute: {
                      defaultValue: IOT_EVENTS
                    }
                  }
                },
                {
                  name: AWS/ALARM_STATE,
                  dataType: STRUCT,
                  dataTypeSpec: AWS/ALARM_STATE,
                  unit: none,
                  type: {
                    measurement: {}
                  }
                }
              ]
          }
        ]
  
  IoTSiteWiseDemoPumpStationAssetModel:
    Type: Custom::IoTSiteWiseDemoPumpStationAssetModel
    DependsOn: [IoTSiteWiseDemoPumpAssetModel, IoTSiteWiseDemoDataGenerationFunctionRole]
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoAssetModelLifecycleFunction, Arn]
      metadata_sitewise_property_ids:
        [
          Total L4E Score,
          Station Abnormaly Threshold
        ]
      name: Demo Pump Station Asset Model
      description: This is an asset model used in the IoT SiteWise Demo for representing a pump station. It will be deleted at the end of the demo.
      properties: 
        [ 
          # Attributes
          { 
            name: Reliability Manager, 
            dataType: STRING, 
            type: { attribute: { defaultValue: Mary Major } }
          },
          {
            name: Code,
            dataType: INTEGER,
            type: { attribute: { defaultValue: 300 } } 
          },
          {
            name: Location,
            dataType: STRING,
            type: { attribute: { defaultValue: Renton } } 
          },
          {
            name: Station Abnormaly Threshold,
            dataType: DOUBLE,
            type: { attribute: { defaultValue: 1.8 } }
          },
          # metric
          {
            name: Total L4E Score,
            dataType: DOUBLE,
            unit: NA,
            type: {
              metric: {
                expression: sum(abnormaly_score),
                variables: [
                  {
                    name: abnormaly_score,
                    value: 
                      { 
                        # Here we are referencing one of the "metadata_sitewise_property_ids" from the IoTSiteWiseDemoTurbineAssetModel
                        propertyId: { "Fn::GetAtt" : [IoTSiteWiseDemoPumpAssetModel, AVG L4E Score id] }, 
                        hierarchyId: Pump Asset Model
                      }
                  }
                ],
                window: { tumbling: { interval: 5m } }
              }
            }
          }
        ]
      hierarchies:
        [
          {
            name: Pump Asset Model,
            childAssetModelId: { Ref: IoTSiteWiseDemoPumpAssetModel }
          }
        ]
      assetModelCompositeModels: [
        {
          name: StationAbnormalyAlarm,
          type: AWS/ALARM,
          properties:
          [
            {
              name: AWS/ALARM_TYPE,
              dataType: STRING,
              unit: none,
              type: {
                attribute: {
                  defaultValue: IOT_EVENTS
                }
              }
            },
            {
              name: AWS/ALARM_STATE,
              dataType: STRUCT,
              dataTypeSpec: AWS/ALARM_STATE,
              unit: none,
              type: {
                measurement: {}
              }
            }
          ]
        }
      ]

  # Assets
  IoTSiteWiseDemoAssetLifecycleFunction:
    Type: AWS::Lambda::Function
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: IoT SiteWise Demo function handling the lifecycle of asset resources. This function will be deleted at the end of the demo.
      Code:
        S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region}
        S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip
      Handler: sitewise_assets.handler
      MemorySize: 128
      Role:
        Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunctionRole, Arn]
      Runtime: python3.7
      Timeout: 900

  IoTSiteWiseDemoAssetLifecycleFunctionRole:
    Type: AWS::IAM::Role
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Role for IoT SiteWise Demo asset lifecycle. This role will be deleted at the end of the demo.
      AssumeRolePolicyDocument:
        Statement:
        - Action: ['sts:AssumeRole']
          Effect: Allow
          Principal:
            Service: [lambda.amazonaws.com]
        Version: '2012-10-17'
      Policies:
      - PolicyName: IoTSiteWiseDemo-AssetLifecycleFunction-RolePolicy
        PolicyDocument:
          Statement:
          # CloudWatch logging
          - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup']
            Effect: Allow
            Resource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
          - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup']
            Effect: Deny
            NotResource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
          # SiteWise
          - Action: ['iotsitewise:CreateAsset','iotsitewise:DescribeAsset','iotsitewise:AssociateAssets','iotsitewise:DisassociateAssets','iotsitewise:DeleteAsset','iotsitewise:UpdateAssetProperty']
            Effect: Allow
            Resource: "*"
          Version: '2012-10-17'

  IoTSiteWiseDemoAssetLifecycleFunctionLogGroup:
    DependsOn: IoTSiteWiseDemoAssetLifecycleFunction
    Type: AWS::Logs::LogGroup
    Condition: ValidRegion
    Properties:
      LogGroupName:
        Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoAssetLifecycleFunction}"

  IoTSiteWiseDemoPumpAsset1:
    DependsOn: [IoTSiteWiseDemoAssetLifecycleFunctionLogGroup, IoTSiteWiseDemoPumpStationAssetModel, IoTSiteWiseDemoPumpL4EAlarmModel]
    Type: Custom::IoTSiteWiseDemoAsset
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunction, Arn]
      name:  Demo Pump Asset 1
      model: { Ref: IoTSiteWiseDemoPumpAssetModel }
      asset_ids_to_associate: []

  IoTSiteWiseDemoPumpAsset2:
    DependsOn: [IoTSiteWiseDemoAssetLifecycleFunctionLogGroup, IoTSiteWiseDemoPumpStationAssetModel, IoTSiteWiseDemoPumpL4EAlarmModel]
    Type: Custom::IoTSiteWiseDemoAsset
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunction, Arn]
      name:  Demo Pump Asset 2
      model: { Ref: IoTSiteWiseDemoPumpAssetModel }
      asset_ids_to_associate: []
  
  IoTSiteWiseDemoPumpStationAsset:
    DependsOn: [IoTSiteWiseDemoAssetLifecycleFunctionLogGroup, IoTSiteWiseDemoStationAbnormalyAlarmModel]
    Type: Custom::IoTSiteWiseDemoAsset
    Condition: ValidRegion
    Properties:
      ServiceToken:
        Fn::GetAtt: [IoTSiteWiseDemoAssetLifecycleFunction, Arn]
      name:  Demo Pump Station Asset
      model: { Ref: IoTSiteWiseDemoPumpStationAssetModel }
      asset_ids_to_associate: [ { Ref: IoTSiteWiseDemoPumpAsset1 }, { Ref: IoTSiteWiseDemoPumpAsset2 } ]

  # Data generation
  IoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Function
    Condition: ValidRegion
    Properties:
      Description: IoT SiteWise Demo function handling data generation. This function will be deleted at the end of the demo.
      Code:
        S3Bucket: !Sub lookoutforequipmentbucket-${AWS::Region}
        S3Key: lambdafunction/L4E-IoTSiteWiseDemoDataGenerationFunction.zip
      Handler: sitewise_data_generation.handler
      MemorySize: 256
      Role:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunctionRole, Arn]
      Runtime: python3.7
      Timeout: 900    

  IoTSiteWiseDemoDataGenerationFunctionRole:
    Type: AWS::IAM::Role
    Condition: ValidRegion
    Properties:
      Description: Role allowing fake data to be generated and put into IoT SiteWise Demo asset properties and stack deletion at the end of the demo. This function will be deleted at the end of the demo.
      AssumeRolePolicyDocument:
        Statement:
        - Action: ['sts:AssumeRole']
          Effect: Allow
          Principal:
            Service: [lambda.amazonaws.com]
        Version: '2012-10-17'
      Policies:
      - PolicyName: IoTSiteWiseDemo-DataGenerationFunction-RolePolicy
        PolicyDocument:
          Statement:
          # CloudWatch logging
          - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup']
            Effect: Allow
            Resource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
          - Action: ['logs:CreateLogStream', 'logs:PutLogEvents', 'logs:CreateLogGroup']
            Effect: Deny
            NotResource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
          # SiteWise
          - Action: ['iotsitewise:BatchPutAssetPropertyValue', 'iotsitewise:DescribeAsset', 'iotsitewise:GetAssetPropertyValue']
            Effect: Allow
            Resource: "*"
          # Stack cleanup
          - Action: ['lambda:DeleteFunction', 'lambda:InvokeFunction', 'lambda:RemovePermission']
            Effect: Allow
            Resource: 
              Fn::Sub: "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${AWS::StackName}-*"
          - Action: ['iam:DeleteRole', 'iam:DeleteRolePolicy']
            Effect: Allow
            Resource: 
              Fn::Sub: "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${AWS::StackName}-*"
            # technically DescribeAsset is used in cleanup but it is already allowed for putting data
          - Action: ['iotsitewise:DisassociateAssets', 'iotsitewise:DeleteAsset', 'iotsitewise:DeleteAssetModel','iotsitewise:UpdateAssetProperty']
            Effect: Allow
            Resource: "*"
          - Action: ['logs:DeleteLogGroup']
            Effect: Allow
            Resource:
              Fn::Sub: "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-*"
          - Action: ['events:RemoveTargets', 'events:DeleteRule']
            Effect: Allow
            Resource: 
              Fn::Sub: "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/${AWS::StackName}-*"
          - Action: ['cloudformation:DescribeStacks', 'cloudformation:DescribeStackEvents', 'cloudformation:DeleteStack']
            Effect: Allow
            Resource: {Ref: 'AWS::StackId'}
          Version: '2012-10-17'

  IoTSiteWiseDemoDataGenerationFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DependsOn: IoTSiteWiseDemoDataGenerationFunction
    Condition: ValidRegion
    Properties:
      LogGroupName:
        Fn::Sub: "/aws/lambda/${IoTSiteWiseDemoDataGenerationFunction}"

  IoTSiteWiseDemoDataGenerationScheduledRule1a:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]                                                                                        
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FirstPropertyGroup}"}' }
  IoTSiteWiseDemoDataGenerationScheduledRule1b:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${SecondPropertyGroup}"}' }
  IoTSiteWiseDemoDataGenerationScheduledRule1c:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${ThirdPropertyGroup}"}' }
  IoTSiteWiseDemoDataGenerationScheduledRule1d:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FourthPropertyGroup}"}' }     
  IoTSiteWiseDemoDataGenerationScheduledRule1e:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset1}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FifthPropertyGroup}"}' }           
  IoTSiteWiseDemoDataGenerationScheduledRule2a:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}","stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FirstPropertyGroup}" }' }     
  IoTSiteWiseDemoDataGenerationScheduledRule2b:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}","stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${SecondPropertyGroup}" }' }                  
  IoTSiteWiseDemoDataGenerationScheduledRule2c:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}","stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${ThirdPropertyGroup}"}' }       
  IoTSiteWiseDemoDataGenerationScheduledRule2d:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FourthPropertyGroup}"}' }
  IoTSiteWiseDemoDataGenerationScheduledRule2e:
    Type: AWS::Events::Rule
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      Description: Executes the IotSiteWiseDemoDataGenerationFunction every minute to generate and put data into IoT SiteWise Demo assets
      ScheduleExpression: rate(1 minute)
      State: "ENABLED"
      Targets:
        - Arn:
            Fn::GetAtt: [IoTSiteWiseDemoDataGenerationFunction, Arn]
          Id: IoTSiteWiseDemoDataGenerationFunction
          Input: { "Fn::Sub" : '{ "turbineAssetId" : "${IoTSiteWiseDemoPumpAsset2}", "stackId" : "${AWS::StackId}", "demoDurationDays" : "${DemoDurationDays}", "PropertyGroup":"${FifthPropertyGroup}"}' }
  IoTSiteWiseDemoDataGenerationScheduledRule1aPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1a, Arn]      
  IoTSiteWiseDemoDataGenerationScheduledRule1bPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1b, Arn]      
  IoTSiteWiseDemoDataGenerationScheduledRule1cPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1c, Arn]   
  IoTSiteWiseDemoDataGenerationScheduledRule1dPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1d, Arn]
  IoTSiteWiseDemoDataGenerationScheduledRule1ePermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule1e, Arn]                   
  IoTSiteWiseDemoDataGenerationScheduledRule2aPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2a, Arn]     
  IoTSiteWiseDemoDataGenerationScheduledRule2bPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2b, Arn]     
  IoTSiteWiseDemoDataGenerationScheduledRule2cPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2c, Arn] 
  IoTSiteWiseDemoDataGenerationScheduledRule2dPermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2d, Arn] 
  IoTSiteWiseDemoDataGenerationScheduledRule2ePermissionToInvokeIoTSiteWiseDemoDataGenerationFunction:
    Type: AWS::Lambda::Permission
    DependsOn: IoTSiteWiseDemoDataGenerationFunctionRole
    Condition: ValidRegion
    Properties:
      FunctionName:
        Ref: IoTSiteWiseDemoDataGenerationFunction
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt: [IoTSiteWiseDemoDataGenerationScheduledRule2e, Arn]                                         