feat: improve MQTT reconnection handling + document arrival notifier
- Add keepalive (60s), reconnectPeriod (5s), connectTimeout (30s) - Add offline/close event handlers with proper logging - Document Tesla Arrival Notifier setup in README - Document systemd service installation
This commit is contained in:
72
README.md
72
README.md
@@ -159,6 +159,78 @@ Messages are prefixed with the topic for context:
|
|||||||
### Webhook returns 401
|
### Webhook returns 401
|
||||||
- Token mismatch — check `hooks.token` in Clawdbot config matches `CLAWDBOT_TOKEN`
|
- Token mismatch — check `hooks.token` in Clawdbot config matches `CLAWDBOT_TOKEN`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tesla Arrival Notifier
|
||||||
|
|
||||||
|
A specialized component that monitors TeslaMate MQTT for car state changes and notifies Clawdbot when you arrive somewhere.
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
1. Subscribes to TeslaMate MQTT topics (`teslamate/cars/<id>/state`, `geofence`, `latitude`, `longitude`)
|
||||||
|
2. Detects when car state transitions from `driving` → any stationary state (`online`, `parked`, `charging`, `suspended`, `asleep`, `offline`)
|
||||||
|
3. Sends arrival notification to Clawdbot with geofence name (or reverse-geocoded address)
|
||||||
|
4. Clawdbot checks `location-reminders.json` for location-specific reminders
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install to /opt
|
||||||
|
sudo mkdir -p /opt/mqtt-clawdbot-bridge
|
||||||
|
sudo cp arrival-notifier.js package*.json /opt/mqtt-clawdbot-bridge/
|
||||||
|
cd /opt/mqtt-clawdbot-bridge && npm install
|
||||||
|
|
||||||
|
# Install systemd service
|
||||||
|
sudo cp arrival-notifier.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable arrival-notifier
|
||||||
|
sudo systemctl start arrival-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Environment variables (configured in the systemd service file):
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `MQTT_URL` | `mqtts://mqtt.teslamate.olex.me:8883` | TeslaMate MQTT broker |
|
||||||
|
| `MQTT_USERNAME` | `olex` | MQTT username |
|
||||||
|
| `MQTT_PASSWORD` | — | MQTT password (**required**) |
|
||||||
|
| `CLAWDBOT_URL` | `http://127.0.0.1:18789` | Clawdbot gateway URL |
|
||||||
|
| `CLAWDBOT_TOKEN` | — | Webhook token (**required**) |
|
||||||
|
| `CAR_ID` | `14` | TeslaMate car ID |
|
||||||
|
| `LOG_LEVEL` | `info` | `debug` for verbose output |
|
||||||
|
|
||||||
|
### Managing the Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
sudo systemctl status arrival-notifier
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
journalctl -u arrival-notifier -f
|
||||||
|
|
||||||
|
# Restart after config changes
|
||||||
|
sudo systemctl restart arrival-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
### Location Reminders
|
||||||
|
|
||||||
|
Create `~/clawd/location-reminders.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Zuhause (Geißberg 31)": [
|
||||||
|
"Reminder: Check the mailbox!"
|
||||||
|
],
|
||||||
|
"Arbeit (GUDE)": [
|
||||||
|
"Remember to submit timesheet on Fridays"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Geofence names must match exactly as shown in TeslaMate.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
|
|||||||
@@ -188,12 +188,17 @@ async function main() {
|
|||||||
username: config.mqtt.username,
|
username: config.mqtt.username,
|
||||||
password: config.mqtt.password,
|
password: config.mqtt.password,
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
|
keepalive: 60, // Send ping every 60s
|
||||||
|
reconnectPeriod: 5000, // Retry every 5s on disconnect
|
||||||
|
connectTimeout: 30000, // 30s connection timeout
|
||||||
};
|
};
|
||||||
|
|
||||||
const client = mqtt.connect(config.mqtt.url, mqttOptions);
|
const client = mqtt.connect(config.mqtt.url, mqttOptions);
|
||||||
const prefix = `teslamate/cars/${config.carId}`;
|
const prefix = `teslamate/cars/${config.carId}`;
|
||||||
|
let isConnected = false;
|
||||||
|
|
||||||
client.on('connect', () => {
|
client.on('connect', () => {
|
||||||
|
isConnected = true;
|
||||||
log.info('Connected to MQTT');
|
log.info('Connected to MQTT');
|
||||||
|
|
||||||
// Subscribe to relevant topics
|
// Subscribe to relevant topics
|
||||||
@@ -235,7 +240,22 @@ async function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
client.on('error', (err) => log.error('MQTT error:', err.message));
|
client.on('error', (err) => log.error('MQTT error:', err.message));
|
||||||
client.on('reconnect', () => log.info('Reconnecting...'));
|
|
||||||
|
client.on('reconnect', () => {
|
||||||
|
log.info('Reconnecting to MQTT...');
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', () => {
|
||||||
|
if (isConnected) {
|
||||||
|
log.info('MQTT connection closed');
|
||||||
|
isConnected = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('offline', () => {
|
||||||
|
log.info('MQTT client offline');
|
||||||
|
isConnected = false;
|
||||||
|
});
|
||||||
|
|
||||||
// Graceful shutdown
|
// Graceful shutdown
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user