283 lines
8.2 KiB
Markdown
283 lines
8.2 KiB
Markdown
# Home control Alexa Skill
|
|
|
|
An Alexa skill that triggers water recirculation on Rinnai tankless water heaters
|
|
and supports homeassistant device control
|
|
|
|
## Usage
|
|
|
|
> "Alexa, ask house to start the hot water"
|
|
|
|
This will authenticate with the Rinnai API and start a 15-minute recirculation cycle.
|
|
|
|
> "Alexa, turn on the bedroom light"
|
|
|
|
This will use the homeassistant REST API to find the bedroom device and turn it on.
|
|
You can turn on, turn off, toggle, and query status
|
|
|
|
## Building
|
|
|
|
Requires [Zig 0.15](https://ziglang.org/) and [mise](https://mise.jdx.dev/) for version management.
|
|
|
|
The build defaults to `aarch64-linux` for AWS Lambda Graviton (arm64) deployment.
|
|
|
|
```bash
|
|
# Debug build (arm64)
|
|
zig build
|
|
|
|
# Release build (arm64)
|
|
zig build -Doptimize=ReleaseFast
|
|
|
|
# Run tests (uses host CPU/OS)
|
|
zig build test
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
- [aws-sdk-for-zig](https://git.lerch.org/lobo/aws-sdk-for-zig) - AWS SDK for Zig
|
|
- [lambda-zig](https://git.lerch.org/lobo/lambda-zig) - AWS Lambda runtime for Zig
|
|
- [controlr](https://git.lerch.org/lobo/controlr) - Rinnai API client (provides `rinnai` module)
|
|
|
|
## Deployment Setup
|
|
|
|
Before deploying, you need to configure both AWS credentials and ASK CLI authentication.
|
|
|
|
### 1. AWS Credentials
|
|
|
|
AWS credentials are required for Lambda deployment. You can configure them in several ways:
|
|
|
|
#### Option A: AWS CLI Configuration (Recommended)
|
|
|
|
```bash
|
|
# Configure default profile
|
|
aws configure
|
|
|
|
# Or configure a named profile
|
|
aws configure --profile personal
|
|
```
|
|
|
|
This creates `~/.aws/credentials` and `~/.aws/config` files.
|
|
|
|
#### Option B: Environment Variables
|
|
|
|
```bash
|
|
export AWS_ACCESS_KEY_ID=AKIA...
|
|
export AWS_SECRET_ACCESS_KEY=...
|
|
export AWS_DEFAULT_REGION=us-west-2
|
|
```
|
|
|
|
#### Using a Non-Default AWS Profile
|
|
|
|
If your default AWS profile is your work account but you want to deploy to your personal account:
|
|
|
|
```bash
|
|
# Set the profile for the current shell session
|
|
export AWS_PROFILE=personal
|
|
|
|
# Or specify it per-command
|
|
zig build awslambda_deploy -Dprofile=personal
|
|
zig build deploy -Dprofile=personal
|
|
```
|
|
|
|
You can also set the region:
|
|
|
|
```bash
|
|
zig build awslambda_deploy -Dprofile=personal -Dregion=us-west-2
|
|
```
|
|
|
|
### 2. ASK CLI Authentication
|
|
|
|
The ASK CLI requires authentication with your Amazon Developer account to deploy Alexa skills.
|
|
|
|
#### First-Time Setup
|
|
|
|
```bash
|
|
# Install dependencies (if not already installed)
|
|
bun install
|
|
|
|
# Configure ASK CLI (opens browser for Amazon login). Note this takes an ungodly
|
|
# amount of time to do anything and it will look like everything is hung
|
|
bun x ask configure
|
|
```
|
|
|
|
This will:
|
|
1. Open your browser to sign in with your Amazon Developer account
|
|
2. Store credentials in `~/.ask/cli_config`
|
|
|
|
#### Verify Authentication
|
|
|
|
```bash
|
|
bun x ask smapi list-skills-for-vendor
|
|
```
|
|
|
|
### 3. Environment Variables
|
|
|
|
The Lambda function needs credentials for the services it interacts with.
|
|
|
|
Create a `.env` file in the project root (this file is gitignored):
|
|
|
|
```bash
|
|
# .env
|
|
|
|
# Rinnai API credentials for water heater control
|
|
COGNITO_USERNAME=your@email.com
|
|
COGNITO_PASSWORD=your_password
|
|
|
|
# Home Assistant configuration
|
|
HOME_ASSISTANT_URL=https://your-homeassistant.example.com
|
|
HOME_ASSISTANT_TOKEN=your_long_lived_access_token
|
|
```
|
|
|
|
#### Rinnai Credentials
|
|
|
|
The `COGNITO_USERNAME` and `COGNITO_PASSWORD` are your Rinnai app login credentials.
|
|
These are used to authenticate with the Rinnai API for water recirculation control.
|
|
|
|
#### Home Assistant Token
|
|
|
|
To generate a long-lived access token in Home Assistant:
|
|
|
|
1. Go to your Home Assistant profile (click your username in the sidebar)
|
|
2. Scroll down to "Long-Lived Access Tokens"
|
|
3. Click "Create Token"
|
|
4. Give it a name (e.g., "Alexa Lambda")
|
|
5. Copy the token immediately (it won't be shown again)
|
|
|
|
The `HOME_ASSISTANT_URL` should be the external URL of your Home Assistant instance.
|
|
|
|
These credentials will be automatically deployed to Lambda when you use the `-Denv-file=.env` option.
|
|
|
|
## Build Steps
|
|
|
|
| Step | Description |
|
|
|------|-------------|
|
|
| `zig build` | Build the bootstrap executable |
|
|
| `zig build test` | Run unit tests |
|
|
| `zig build awslambda_package` | Package Lambda function into zip |
|
|
| `zig build awslambda_iam` | Create/verify IAM role |
|
|
| `zig build awslambda_deploy` | Deploy Lambda function to AWS |
|
|
| `zig build awslambda_run` | Invoke the deployed Lambda function |
|
|
| `zig build ask_deploy` | Deploy Alexa skill metadata |
|
|
| `zig build deploy` | Deploy both Lambda and Alexa skill |
|
|
|
|
### Build Options
|
|
|
|
| Option | Description | Default |
|
|
|--------|-------------|---------|
|
|
| `-Doptimize=ReleaseFast` | Build with optimizations | Debug |
|
|
| `-Dtarget=native` | Build for local machine | aarch64-linux |
|
|
| `-Dfunction-name=NAME` | Lambda function name | exe name (house-control) |
|
|
| `-Dprofile=PROFILE` | AWS profile to use | default |
|
|
| `-Dregion=REGION` | AWS region | from profile |
|
|
| `-Drole-name=ROLE` | IAM role name | lambda_basic_execution |
|
|
| `-Dpayload=JSON` | Payload for `awslambda_run` | {} |
|
|
| `-Denv-file=PATH` | Environment variables file | none |
|
|
|
|
## Deployment
|
|
|
|
### Prerequisites
|
|
|
|
Before deploying, ensure you have:
|
|
|
|
1. **AWS Account** with credentials configured (see [Deployment Setup](#deployment-setup))
|
|
2. **Amazon Developer Account** with ASK CLI authenticated (`bun x ask configure`)
|
|
3. **Credentials** in `.env` file (see [Environment Variables](#3-environment-variables)):
|
|
- Rinnai account credentials (for water recirculation)
|
|
- Home Assistant URL and long-lived access token (for device control)
|
|
|
|
### Full Deployment (Lambda + Alexa Skill)
|
|
|
|
```bash
|
|
zig build deploy -Doptimize=ReleaseFast \
|
|
-Dprofile=personal \
|
|
-Dregion=us-west-2 \
|
|
-Denv-file=.env
|
|
```
|
|
|
|
This command orchestrates a multi-step deployment pipeline:
|
|
|
|
1. **Build** - Compile Lambda function for arm64
|
|
2. **Package** - Create deployment zip with bootstrap executable
|
|
3. **Deploy Lambda** - Create/update function in AWS, set env vars from `.env`
|
|
4. **Generate skill.json** - Inject Lambda ARN into `skill.template.json`
|
|
5. **ASK Deploy** - Deploy Alexa skill metadata and interaction model
|
|
6. **Add Permission** - Grant Alexa permission to invoke Lambda with skill-specific token
|
|
|
|
The permission step uses the skill ID (from `.ask/ask-states.json`) as an
|
|
`event_source_token` condition, restricting invocation to only this specific
|
|
Alexa skill rather than allowing any Alexa skill to invoke the Lambda.
|
|
|
|
### Lambda Only
|
|
|
|
```bash
|
|
zig build awslambda_deploy -Doptimize=ReleaseFast \
|
|
-Dprofile=personal \
|
|
-Dregion=us-west-2 \
|
|
-Denv-file=.env
|
|
```
|
|
|
|
Note: This only deploys the Lambda function. To invoke the function from Alexa,
|
|
you must also deploy the skill (`zig build deploy`) to set up the permission.
|
|
|
|
### Alexa Skill Only
|
|
|
|
```bash
|
|
zig build ask_deploy
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
water_recirculation/
|
|
├── build.zig # Build configuration
|
|
├── build.zig.zon # Dependencies
|
|
├── .env # Credentials (gitignored)
|
|
├── skill.template.json # Skill manifest template (Lambda ARN placeholder)
|
|
├── ask-resources.json # ASK CLI deployment config
|
|
├── package.json # Node.js deps for ASK CLI
|
|
├── src/
|
|
│ ├── main.zig # Lambda entry point
|
|
│ └── homeassistant.zig # Home Assistant API client
|
|
├── tools/
|
|
│ ├── gen-skill-json.zig # Generates skill.json from template
|
|
│ └── add-alexa-permission.zig # Adds skill-specific Lambda permission
|
|
├── skill-package/
|
|
│ ├── skill.json # Generated (gitignored)
|
|
│ └── interactionModels/
|
|
│ └── custom/
|
|
│ └── en-US.json # Interaction model with intents/slots
|
|
└── .ask/
|
|
└── ask-states.json # ASK CLI state (contains skill ID)
|
|
```
|
|
|
|
## Sample Utterances
|
|
|
|
### Water Recirculation
|
|
- "start the hot water"
|
|
- "turn on the hot water"
|
|
- "heat the water"
|
|
- "preheat the water"
|
|
- "start recirculation"
|
|
- "warm up the water"
|
|
|
|
### Home Assistant Device Control
|
|
- "turn on the bedroom light"
|
|
- "turn off the kitchen"
|
|
- "toggle the basement fireplace"
|
|
- "is the deck on"
|
|
- "check the family room"
|
|
|
|
## Lambda Details
|
|
|
|
- **Function**: `house-control`
|
|
- **Region**: us-west-2
|
|
- **Architecture**: arm64 (Graviton)
|
|
- **Runtime**: provided.al2023
|
|
|
|
## Alexa Skill
|
|
|
|
- **Skill ID**: `amzn1.ask.skill.5cc9bf04-8be9-4229-936d-49a22fae6a3e`
|
|
- **Invocation**: "Alexa, ask house to..."
|
|
|
|
## License
|
|
|
|
MIT
|