Project Doorbell is an idea that I got to know the managed AI AWS services and to keep going to write some code in Rust.
Working with people is more fun but require a bit of organization.
Project doorbell will be part of a series to document my steps to deliver a working proof of concept.
Smart doorbell
Smart doorbells include a camera, microphone and speaker to allow for a two-way conversation between the doorbell and its smartphone app.
This project is concentrated on the backend side of communication. Therefore, I will not consider the hardware and the mobile app.
I will assume they exist to facilitate this PoC.
For example, I will use Amazon API Gateway with WebSocket because they are bidirectional, and this behaviour enables me to interact between the device and the AWS services.
Probably the best fit is AWS IoT because it connects IoT devices to other devices and AWS cloud services. I am unfamiliar with this service and the MQTT over WSS protocol, so I deliberately decided to use Amazon API Gateway with WebSocket. I will try to use AWS IoT later on for future development.
How it works
The doorbell connects to the WebSocket API by sending a WebSocket request. If the request succeeds, an event is emitted.
This event will trigger a Lambda function that will generate a presigned URL, and thanks to the WebSocket, will send it to the doorbell. Presigned URL is needed because all objects, by default, are private. By creating a presigned URL, I can grant time-limited permission to upload the photo taken by the doorbell.
Once the upload is completed, an event is emitted, and it will execute AWS Step Functions, where the photo taken by the doorbell is compared against a set of source photos of the owner(s). In this PoC, I will assume only one owner.
If the photo match, a six-digit code will be sent to the owner device and with this code entry, the owner can access the property.
If the photo does not match, we have two options:
- leave the doorbell ring
- send the photo to the owner device, where it is possible to review it and decide on some action.
GitHub
I am using GitHub, and there is no need for introduction, but just in case here, you find a short and fun lab.
Because this time I have a collaborator, I need to share my ideas and what I have in my mind, so I have found the excuse to use the issue sections and the dashboard.
You are free to tag along if you want. I will try my best to involve you or satisfy your requests.
The repository is available on GitHub.
Infrastructure
The current solution is composed mainly by:
- Amazon API Gateway with WebSocket
- AWS S3
- AWS Step Functions
- Lambda functions
I will show the relative new configuration to connect AWS S3 with AWS Step Function by Amazon EventBridge.
AWS S3
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: S3 Bucket to store the photos
Resources:
##########################################################################
# S3 #
##########################################################################
SourceBucket:
Type: AWS::S3::Bucket
Properties:
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: True
LifecycleConfiguration:
Rules:
- Id: DeleteLifeCyclePolicy
Status: Enabled
ExpirationInDays: 1
##########################################################################
# BUCKET POLICY #
##########################################################################
SourceBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref SourceBucket
PolicyDocument:
Statement:
- Action: s3:*
Effect: Deny
Principal: "*"
Resource:
- !Sub "arn:aws:s3:::${SourceBucket}/*"
- !Sub "arn:aws:s3:::${SourceBucket}"
Condition:
Bool:
aws:SecureTransport: false
Outputs:
SourceBucketName:
Value: !Ref SourceBucket
Export:
Name: SourceBucket
SourceBucketArn:
Value:
Fn::GetAtt:
- SourceBucket
- Arn
Export:
Name: SourceBucketArn
I want to highlight the following part.
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: True
NotificationConfiguration describes the notification configuration for an Amazon S3 bucket. Amazon S3 can send events to Amazon EventBridge whenever certain events happen in your bucket.
Under SourceBucketName, we export the bucket name, which is how to share information between stacks. Then, other stacks in the same AWS account and region can import the exported values.
Outputs:
SourceBucketName:
Value: !Ref SourceBucket
Export:
Name: SourceBucket
AWS Step Functions
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: StepFunctions state machine
Resources:
##########################################################################
# STEP FUNCTION #
##########################################################################
MyStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: statemachine/stateMachine.asl.json
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "cloudwatch:*"
- "logs:*"
- "rekognition:CompareFaces"
Resource: "*"
- Effect: Allow
Action:
- "s3:GetObject"
Resource:
- !ImportValue SourceBucketArn
Logging:
Destinations:
- CloudWatchLogsLogGroup:
LogGroupArn: !GetAtt MyStateMachineLogGroup.Arn
IncludeExecutionData: false
Level: 'ALL'
Events:
StateChange:
Type: EventBridgeRule
Properties:
InputPath: $.detail
Pattern:
source:
- aws.s3
detail:
bucket:
name:
- !ImportValue SourceBucket
reason:
- PutObject
##########################################################################
# STEP FUNCTION LOG GROUP #
##########################################################################
MyStateMachineLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join [ "/", [ "stepfunctions", MyStateMachine]]
Outputs:
MyStateMachine:
Value: !Ref MyStateMachine
Description: MyStateMachine Arn
I want to highlight the integration to trigger AWS Step Functions with Amazon EventBridge.
Events:
StateChange:
Type: EventBridgeRule
Properties:
InputPath: $.detail
Pattern:
source:
- aws.s3
detail:
bucket:
name:
- !ImportValue SourceBucket
reason:
- PutObject
When the delivery of events to EventBridge is enabled, Amazon S3 will send all events to EventBridge, and so for my case, I listen only to events for:
- The bucket where we upload the photo (reference from the output section of the s3 template)
- PutObject actions
Conclusion
It is an amateur project to play around with. Still, a project board or writing down stories help you organize and prioritize the work, and GitHub allows you easily to add collaboration to your project. Starting with infrastructure as code (IaC) makes things faster by eliminating manual processes and eliminating errors. Additionally, I found it helpful with the principle of least privilege because usually, from the AWS console, I set full access to make it works while writing IaC help me apply the bare minimum permission to perform the task.