This project provides a Home Assistant add-on for integrating SmartDoor smart garage door systems with Home Assistant via MQTT.
Repository: https://github.com/gravypower/dd
The project consists of three main executables:
register(bin/register) - One-time credential registration with SmartDoor cloud serversaction(bin/action) - CLI utility for sending direct commands to devices (for testing)haus(bin/haus) - Main daemon that bridges SmartDoor devices with Home Assistant via MQTT
┌─────────────────────┐
│ Home Assistant │
│ (MQTT Client) │
└──────────┬──────────┘
│ MQTT Protocol
│ (Commands & Status)
┌──────────▼──────────┐
│ haus Daemon │
│ - MQTT Bridge │
│ - FSM Manager │
│ - Status Polling │
└──────────┬──────────┘
│ Encrypted API
│ (AES-CBC, HMAC)
┌──────────▼──────────┐
│ SmartDoor Device │
│ (Local Network) │
│ Ports: 8989, 8991 │
└─────────────────────┘
-
Root Package (
github.com/gravypower/dd)conn.go- Device connection & encrypted communicationcrypto.go- AES-CBC encryption/decryption, HMAC signingtypes.go- Core data structures (Conn, Credential, Message, RPC)cert.go- Embedded SSL certificates for SmartDoor CA
-
API Package (
github.com/gravypower/dd/api)haus.go- MQTT integration & finite state machine logicdevices.go- Device status structures and fetchingcommand.go- Command execution wrapperavailableCommands.go- Complete command mapping (40+ commands)info.go- Basic device information retrieval
-
Helper Package (
github.com/gravypower/dd/helper)creds.go- Credential loading from JSON filesmessages.go- Background message polling loop
-
Executables (
bin/)register/main.go- Credential registrationaction/main.go- Direct command executionhaus/main.go- Main Home Assistant integration daemon
SmartDoor devices expose two HTTPS endpoints:
- Basic device information endpoint
- Example:
/sdk/inforeturns device name, version, basestation ID
- All authenticated operations
- AES-CBC encryption with MD5-derived IV
- HMAC-SHA256 request signing
- Session-based authentication
-
Connection (
/app/connect)- Send credentials (base station ID, phone ID, phone secret)
- Receive session ID and session secret
- Establish next access timestamp
-
Signed Requests
- Each request signed with both session and phone signatures
- Timestamp coordination using
nextAccessmechanism - Process ID tracking for async RPC responses
-
Message Polling (
/app/res/messages)- Background polling for device status updates
- Encrypted message payloads
- Process ID matching for RPC responses
-
Command Execution (
/app/res/action)- Send device commands (open, close, stop, etc.)
- Percentage-based positioning (5%-95%)
- Light, camera, and lockout controls
- Algorithm: AES-CBC
- Key Derivation: MD5 hash of phone secret (16 bytes for AES-128)
- IV Derivation: MD5 hash of timestamp
- Padding: PKCS5
- Signature: HMAC-SHA256(timestamp:data)
The daemon publishes MQTT discovery configuration for automatic device setup:
Topic: homeassistant/cover/{deviceID}/config
Payload: {
"name": "Device Name",
"command_topic": "dd-door/{deviceID}/command",
"state_topic": "dd-door/{deviceID}/state",
"availability_topic": "dd-door/{deviceID}/availability",
"device_class": "garage",
...
}
-
Command Topic:
dd-door/{deviceID}/command- Payloads:
go_open,go_close,STOP
- Payloads:
-
State Topic:
dd-door/{deviceID}/state- Payloads:
opening,closing,open,closed,stopping
- Payloads:
-
Position Topic:
dd-door/{deviceID}/position⭐ NEW- Payloads:
0to100(integer, current door position)
- Payloads:
-
Set Position Topic:
dd-door/{deviceID}/set_position⭐ NEW- Payloads:
0to100(integer, desired door position)
- Payloads:
-
Availability Topic:
dd-door/{deviceID}/availability- Payloads:
online,offline
- Payloads:
Each device is managed by a state machine with the following states:
States:
initial → online → {opening, closing, open, closed, stopping, stopped}
↓
offline
Events:
go_online, go_offline, go_open, go_close, go_opened, go_closed, go_stop, go_stopped
Transitions:
- go_online: initial/offline → online
- go_open: online/closed/stopped → opening
- go_opened: * → open
- go_close: online/open/stopped → closing
- go_closed: * → closed
- go_stop: online/opening/closing → stopping
- go_offline: * → offline
- Open (2) - Fully open door
- Close (4) - Fully close door
- Stop (3) - Stop door movement
The add-on now supports precise position control via Home Assistant's position slider!
Slider Control: Set any position from 0% (closed) to 100% (open) with 5% granularity.
Common Use Cases:
- Pet Mode (20%) - Perfect height for pets
- Delivery Mode (68%) - Package drop-off without full access
- Ventilation (5-10%) - Air circulation
- Custom Heights - Any position in 5% increments
Implementation: Uses GetCommandForPosition() to map positions to device commands (32-50).
See POSITION_CONTROL.md for detailed usage and examples.
- PartOpen1 (5) - Pet mode (~20%)
- PartOpen2 (6) - Parcel mode (~68%)
- PartOpen3 (7) - Custom height
- Commands 32-50 for 5% to 95% positioning in 5% increments
- Light On/Off (16, 17)
- Aux On/Off (18, 19)
- Phone Lockout (257, 258)
- Remote Control Lockout (20, 21)
- Camera Alarms (352-355)
- Cycle Testing (321, 322)
The dd directory contains the Home Assistant add-on configuration:
- Multi-architecture Docker support (aarch64, amd64, armhf, armv7, i386)
- S6-overlay for process management
- AppArmor security profile
- Automatic credential registration on first run
Basic configuration (uses Home Assistant MQTT automatically):
code: "registration_code" # From SmartDoor app
password: "registration_password"
host: "192.168.1.x" # Local device IP
mqtt_prefix: "dd-door" # Optional, customize MQTT topic prefix
debug: falseAdvanced: Custom MQTT broker (optional):
code: "registration_code"
password: "registration_password"
host: "192.168.1.x"
mqtt: # Only needed for custom brokers
broker: "192.168.1.50"
port: 1883
username: "mqtt_user"
password: "mqtt_pass"
mqtt_prefix: "dd-door"
debug: false- Credentials stored in
/config/dd-credentials.json(plaintext) - SSL/TLS validation uses embedded SmartDoor CA certificates
- All device communication encrypted with AES-CBC
- HMAC-SHA256 signatures prevent request tampering
- Session-based authentication with server-provided secrets
- Global
DeviceFSMsmap protected bysync.RWMutex - Thread-safe helper functions:
GetDeviceFSM(),SetDeviceFSM(),GetAllDeviceFSMs() - MQTT publish operations protected by mutex
- FSM callbacks acquire locks before modifying state
- API functions return errors instead of calling
Fatal() - Graceful degradation when MQTT connection is temporarily lost
- Auto-reconnect for MQTT with persistent sessions
- Retry logic for configuration publishing
- Contextual error messages for crypto failures
go build -o register ./bin/register
go build -o action ./bin/action
go build -o haus ./bin/hausgo test ./... # All tests
go test ./api -v # API package tests
go test -run TestEncryptDecrypt # Specific test- Add command constant to
api/availableCommands.go - Update
AvailableCommandsMapwith string mapping - Document the command code range in comments