# # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # *********************** IMPORTANT *********************** # This lambda function is part of the traffic light example and requires # both lightController.py and trafficLight.py to work properly. # It also requires setup steps including permissions. Please refer to # Module 6 in Greengrass getting started guide for directions. # # Because this Lambda creates a small table in DynamoDB, you may be charged # for creating a table. Please refer to DynamoDB Pricing here: # https://aws.amazon.com/dynamodb/pricing/ # # ************************************************************************** # This example demonstrates how a shadow state can be tracked in a long-lived # lambda and how to interface with DynamoDB. This lambda function listens # to shadow MQTT message on light status, and when the light is green, # it generates a random number to represent the number of cars that have passed. # This function stores statistics on these numbers and uploads them to DynamoDB # on every fourth green light. Since this function is long-lived it # will run forever when deployed to a Greengrass core. import logging from datetime import datetime from random import randint import boto3 from botocore.exceptions import ClientError # Initialized DynamoDB client # Note this creates a dynamodb table in region us-east-1 (N. Virginia) # Change the region name to something different if you like # Note endpoint and aws credentials are not specified. By default this # uses the credentials configured for the session. See Boto 3 docs # for more details. dynamodb = boto3.resource("dynamodb", region_name="us-east-1") tableName = "CarStats" # Create the dynamo db table if needed try: table = dynamodb.create_table( TableName=tableName, KeySchema=[{"AttributeName": "Time", "KeyType": "HASH"}], # Partition key AttributeDefinitions=[{"AttributeName": "Time", "AttributeType": "S"}], ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, ) # Wait until the table exists. table.meta.client.get_waiter("table_exists").wait(TableName=tableName) except ClientError as e: if e.response["Error"]["Code"] == "ResourceInUseException": print("Table already created") else: raise e # initialize the logger logger = logging.getLogger() logger.setLevel(logging.INFO) # This is a long lived lambda so we can keep state as below totalTraffic = 0 totalGreenlights = 0 minCars = -1 maxCars = -1 # This handler is called when an event is sent via MQTT # Event targets are set in subscriptions settings # This should be set up to listen to shadow document updates # This function gets traffic light updates from the shadow MQTT event # On every Green light it does the following: # passing cars are simulated by a random number 1 <= n <= 20 # the minimum and maximum cars passing during a green light are tracked # the total number of cars passing during all green lights are tracked # On every 3rd Green light these stats are sent to CarStats dynamodb table # using a timestamp as the hash key def function_handler(event, context): global totalTraffic global totalGreenlights global minCars global maxCars # grab the light status from the event # Shadow JSON schema: # { "state": { "desired": { "property": } } } logger.info(event) lightValue = event["current"]["state"]["reported"]["property"] logger.info("reported light state: " + lightValue) if lightValue == "G": logger.info("Green light") # generate a random number of cars passing during this green light cars = randint(1, 20) # update stats totalTraffic += cars totalGreenlights += 1 if cars < minCars or minCars == -1: minCars = cars if cars > maxCars: maxCars = cars logger.info("Cars passed during green light: " + str(cars)) logger.info("Total Traffic: " + str(totalTraffic)) logger.info("Total Greenlights: " + str(totalGreenlights)) logger.info("Minimum Cars passing: " + str(minCars)) logger.info("Maximum Cars passing: " + str(maxCars)) # update car stats to dynamodb every 3 green lights if totalGreenlights % 3 == 0: global tableName table = dynamodb.Table(tableName) table.put_item( Item={ "Time": str(datetime.utcnow()), "TotalTraffic": totalTraffic, "TotalGreenlights": totalGreenlights, "MinCarsPassing": minCars, "MaxCarsPassing": maxCars, } ) return