A lightweight handheld cloud control firmware for the M5Stack Cardputer v1.1. It enables secure monitoring and management of AWS EC2 instances directly from a portable device.
PocketCloud Terminal turns your M5Stack Cardputer into a portable EC2 remote controller. It connects to Wi-Fi, fetches instance states, and can start or stop instances using a secure API Gateway/Lambda proxy.
Architecture Flow:
Cardputer -> Wi-Fi -> Authentication -> API Gateway + Lambda -> AWS EC2
- Device: M5Stack Cardputer v1.1
- SoC: ESP32-S3 (Xtensa dual-core @ 240MHz)
- Flash: 8MB
- PSRAM: 16MB
- Wi-Fi: 2.4GHz only (ESP32-S3 does not support 5GHz)
| Parameter | Value |
|---|---|
| Loop task stack | 32KB (increased for TLS + HTTPClient) |
| Monitor speed | 115200 baud |
| Flash speed | 921600 |
| Partition scheme | default (8MB flash) |
| Library | Version | Purpose |
|---|---|---|
| M5Cardputer | ^1.1.1 | Cardputer hardware abstraction |
| M5Unified | ^0.2.14 | Unified M5Stack API |
| M5GFX | ^0.2.20 | Graphics rendering |
| ArduinoJson | ^6.21.6 | JSON serialization |
Any region with API Gateway and Lambda support. Ensure the Lambda function is deployed to the same region as your EC2 instances.
aws-cardputer/
├── DEPLOYMENT_GUIDE.md # Comprehensive deployment and setup instructions
├── README.md # This document
├── include/
│ └── hardware_config.h # Hardware constants and configuration
├── lambda/
│ └── ec2_proxy/
│ ├── deploy.ps1 # Windows deployment script for AWS SAM
│ ├── handler.py # Lambda backend Python logic
│ ├── requirements.txt # Lambda dependencies
│ └── template.yaml # AWS SAM template for the API proxy
├── platformio.ini # PlatformIO build configuration
└── src/
└── main.cpp # Main firmware source code
- Boot: The device boots and plays an animated initialization sequence.
- Network: It connects to a saved Wi-Fi network or prompts the user to scan and connect.
- Setup: The device loads AWS credentials from non-volatile storage (NVS) or SD card. An embedded local web server starts, allowing easy configuration via a browser.
- Fetching: The user presses
[E]to fetch EC2 instances. The firmware authenticates with AWS via the API proxy. - Control: The display lists instances with color-coded status indicators. The user selects an instance and presses
[T]or[E]to toggle power (start/stop).
# Clone the repository
git clone https://github.com/ch1n7u/aws-cardputer.git
cd aws-cardputer
# Install PlatformIO dependencies
pio lib install
# Build the firmware
pio runUpload the firmware to the Cardputer over USB using PlatformIO:
# Upload to device
pio run --target upload
# Monitor serial output
pio device monitor --baud 115200To securely route requests from your Cardputer to your AWS EC2 instances, deploy the backend proxy to your AWS account. The backend uses API Gateway, AWS Lambda, and DynamoDB.
Before deploying the backend proxy, ensure you have set up your AWS environment:
- AWS Account: You need an active AWS Account.
- IAM User: Create an IAM User with AdministratorAccess, or equivalent permissions for CloudFormation, Lambda, API Gateway, IAM, and DynamoDB.
- AWS CLI Setup: Install the AWS CLI and run
aws configureto set yourAWS Access Key ID,AWS Secret Access Key, and default region name, for exampleap-south-1. - AWS SAM CLI: Install the AWS SAM CLI.
- Open PowerShell and, if script execution is restricted, allow local scripts for this session:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser- Change into the backend deployment folder:
cd .\lambda\ec2_proxy- Deploy the stack. The script runs
sam buildandsam deployfor you, and it generates missing secrets if you do not pass them:
.\deploy.ps1 -StackName "ec2-proxy-stack" -Region "ap-south-1"If you want to provide your own values instead of auto-generated secrets:
.\deploy.ps1 -StackName "ec2-proxy-stack" -Region "ap-south-1" -AdminToken "YOUR_ADMIN_TOKEN" -PairCode "YOUR_PAIR_CODE" -TokenSigningKey "YOUR_TOKEN_SIGNING_KEY"After the script completes it will print only the AdminToken, PairCode, and the API Gateway URL. Please save these values and update the device configuration in the web interface.
- If you need to run the SAM build manually, use:
sam build --template-file template.yamlConfiguration can be performed directly on the device by pressing [S] or via the local web interface by navigating to the device's IP address.
Configuration Options:
- AWS Proxy: API Gateway URL, Pair Code, Legacy Admin Token.
- Security: Device 4-digit PIN lock.
- Network: Wi-Fi SSID and Password.
Settings can be exported/imported using an SD card with an /ec2.conf file.
- Proxy Auth: Pair code exchange retrieves short-lived access and refresh tokens, verified via HMAC SHA-256 using a hardware-bound key derived from the device's ESP32 MAC address.
- Storage Security: NVS credentials are XOR encoded with a key derived from
ESP.getEfuseMac()(format:XXXXXXXXXXXXXXXX). Encrypted values are stored as hex strings (token_enc,pair_code_enc, etc.). - Access Control: On-device settings UI is protected by a 4-digit PIN.
- PIN Recovery: If PIN is forgotten, flash firmware via USB to reset. SD card config file import also requires physical access to the device.
- Device + Pair Code →
/pair→ Access Token (short TTL) + Refresh Token - Access Token expired →
/refresh→ New Access Token (using Refresh Token) - Credentials stored encrypted in NVS
TLS certificate validation requires accurate system time. On first boot or after extended storage, the device syncs time via NTP before any HTTPS request. If time sync fails, a fallback timestamp (2025-01-01) is used, which may cause TLS verification failures for some endpoints.
The device communicates with the EC2 proxy via the following endpoints:
Purpose: Register device and exchange pair code for tokens.
Request:
{
"deviceId": "cardputer-XXXXXXXX",
"pairCode": "XXXX-XXXX"
}Response (200):
{
"accessToken": "<jwt-or-opaque-token>",
"refreshToken": "<opaque-token>",
"expiresIn": 3600
}Purpose: Refresh expired access token.
Request:
{
"deviceId": "cardputer-XXXXXXXX",
"refreshToken": "<refresh-token>"
}Response (200): Same as /pair
Purpose: List EC2 instances authorized for this device.
Headers:
Authorization: Bearer <access-token>X-Device-Id: cardputer-XXXXXXXX
Response (200):
{
"instances": [
{
"InstanceId": "i-0123456789abcdef0",
"Name": "web-server-prod",
"State": "running"
}
]
}Purpose: Execute action on an instance.
Actions: start, stop, reboot
| Symptom | Likely Cause | Fix |
|---|---|---|
| Upload failures | USB cable / driver issue | Unplug/replug USB cable. Install M5Stack UART drivers. |
| Wi-Fi won't connect | Wrong band selected | Ensure connecting to 2.4GHz network (ESP32-S3 doesn't support 5GHz) |
| Wi-Fi won't connect | Wrong password | Press W to re-enter credentials |
| "Clock sync failed" | NTP blocked/failed | Check internet access. Device attempts pool.ntp.org, time.google.com, time.aws.com |
| AWS auth failure | Invalid pair code | Verify pair code via web interface /debug endpoint |
| "Unauthorized" error | Tokens expired | Re-pair device via web interface, or update pair code in settings |
| TLS errors | System time wrong | After extended storage, force NTP sync by toggling Wi-Fi |
| SD config import fails | Wrong file format | Must be FAT32. Required file: /ec2.conf (see format below) |
| SAM CLI not found | Not in PATH | Install AWS SAM CLI and restart terminal |
The SD card must be formatted as FAT32. Place /ec2.conf in the root:
url=https://abc123.execute-api.region.amazonaws.com/Prod
token_enc=<xor-hex-encoded-token>
pair_code_enc=<xor-hex-encoded-pair-code>
device_id=cardputer-XXXXXXXX
Navigate to http://<device-ip>/debug in a browser to see:
- Wi-Fi status and IP
- Token and pair code state
- System clock value
- Last EC2 error message
| Limitation | Detail |
|---|---|
| No SSH | SSH terminal access is NOT currently implemented |
| Wi-Fi bands | Only supports 2.4GHz (ESP32-S3 hardware limitation) |
| Instance display | Abbreviated names (max 24 chars shown on screen) |
| Instance list | Capped at MAX_INSTANCES compile-time constant to conserve RAM |
| Token storage | Credentials encoded, not encrypted — physical access to device + SD card extraction could expose data |
| PIN storage | PIN is stored as XOR-encode, not hashed — determined attacker could recover |
| Feature | Status |
|---|---|
| Wi-Fi connection | ✅ Implemented |
| EC2 instance list | ✅ Implemented |
| Start/Stop/Reboot EC2 | ✅ Implemented |
| Web configuration UI | ✅ Implemented |
| SD card config import | ✅ Implemented |
| PIN lock | ✅ Implemented |
| SSH terminal | 🔜 Planned |
| Command relay mode | 🔜 Planned |
| ANSI color terminal | 🔜 Planned |
Contributions are welcome! Please adhere to standard pull request workflows and ensure the firmware builds successfully before submitting changes.
This project is open-source and licensed under the MIT License.
