Skip to content

Commit 8a1ee9f

Browse files
Yerazeclaude
andauthored
feat: expose auto responder tokens as environment variables (#2314) (#2356)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c50f0fb commit 8a1ee9f

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

docs/developers/auto-responder-scripting.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,15 +366,30 @@ All scripts receive these environment variables:
366366
|----------|-------------|---------|
367367
| `MESSAGE` | Full message text received | `"weather miami"` |
368368
| `FROM_NODE` | Sender's node number | `"123456789"` |
369-
| `FROM_SHORT_NAME` | Sender's short name (if known) | `"JOHN"` |
370-
| `FROM_LONG_NAME` | Sender's long name (if known) | `"John Doe"` |
369+
| `NODE_ID` | Sender's node ID (hex format) | `"!a2e4ff4c"` |
370+
| `SHORT_NAME` | Sender's short name (if known) | `"JOHN"` |
371+
| `LONG_NAME` | Sender's long name (if known) | `"John Doe"` |
372+
| `FROM_SHORT_NAME` | Sender's short name (alias for `SHORT_NAME`) | `"JOHN"` |
373+
| `FROM_LONG_NAME` | Sender's long name (alias for `LONG_NAME`) | `"John Doe"` |
371374
| `FROM_LAT` | Sender's latitude (if known) | `"25.7617"` |
372375
| `FROM_LON` | Sender's longitude (if known) | `"-80.1918"` |
373376
| `MM_LAT` | MeshMonitor node's latitude (if known) | `"25.7617"` |
374377
| `MM_LON` | MeshMonitor node's longitude (if known) | `"-80.1918"` |
378+
| `HOPS` | Number of hops the message traveled | `"2"` |
379+
| `SNR` | Signal-to-noise ratio of received packet | `"6.25"` |
380+
| `RSSI` | Received signal strength indicator | `"-98"` |
381+
| `CHANNEL` | Channel number the message was received on | `"0"` |
382+
| `VERSION` | Sender's firmware version (if known) | `"2.5.6.a1b2c3d"` |
383+
| `NODECOUNT` | Number of active nodes on the mesh | `"42"` |
384+
| `VIA_MQTT` | Whether message arrived via MQTT bridge | `"true"` |
385+
| `IS_DIRECT` | Whether the message is a direct message | `"true"` |
375386
| `PACKET_ID` | Message packet ID | `"987654321"` |
387+
| `MESHTASTIC_IP` | IP address of the connected Meshtastic node | `"192.168.1.100"` |
388+
| `MESHTASTIC_PORT` | TCP port of the connected Meshtastic node | `"4403"` |
376389
| `TRIGGER` | Trigger pattern that matched | `"weather {location}"` |
390+
| `MATCHED_PATTERN` | The specific pattern that matched | `"weather {location}"` |
377391
| `PARAM_*` | Extracted parameters | `PARAM_location="miami"` |
392+
| `MSG_*` | All message fields as individual variables | `MSG_text="weather miami"` |
378393
| `TZ` | Server timezone (IANA timezone name) | `"America/New_York"` |
379394

380395
### Location Environment Variables

docs/features/automation.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,22 @@ Scripts must:
890890
All scripts receive these environment variables:
891891
- `MESSAGE`: Full message text received
892892
- `FROM_NODE`: Sender's node number
893+
- `NODE_ID`: Sender's node ID (hex format, e.g., `!a2e4ff4c`)
894+
- `LONG_NAME` / `SHORT_NAME`: Sender's node names
895+
- `HOPS`: Number of hops the message traveled
896+
- `SNR` / `RSSI`: Signal quality of received packet
897+
- `CHANNEL`: Channel number the message was received on
898+
- `VERSION`: Sender's firmware version
899+
- `NODECOUNT`: Number of active nodes on the mesh
900+
- `VIA_MQTT`: Whether message arrived via MQTT bridge
901+
- `IS_DIRECT`: Whether the message is a direct message
902+
- `MESHTASTIC_IP` / `MESHTASTIC_PORT`: Connected node address
893903
- `PACKET_ID`: Message packet ID
894904
- `TRIGGER`: The trigger pattern that matched
895905
- `PARAM_*`: Extracted parameters (e.g., `PARAM_location`, `PARAM_name`)
906+
- `MSG_*`: All message fields as individual variables
907+
908+
See the [Auto Responder Scripting Guide](/developers/auto-responder-scripting#environment-variables) for the complete list.
896909

897910
**JSON Output Format**:
898911

src/server/meshtasticManager.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7857,7 +7857,9 @@ class MeshtasticManager {
78577857
const { promisify } = await import('util');
78587858
const execFileAsync = promisify(execFile);
78597859

7860-
const scriptEnv = await this.createScriptEnvVariables(message, matchedPattern, extractedParams, trigger, packetId);
7860+
const scriptEnv = await this.createScriptEnvVariables(message, matchedPattern, extractedParams, trigger, packetId, {
7861+
nodeId, hopsTraveled, isDirectMessage
7862+
});
78617863

78627864
// Expand tokens in script args if provided
78637865
let scriptArgsList: string[] = [];
@@ -8050,7 +8052,14 @@ class MeshtasticManager {
80508052
* - MSG_*: All message fields (e.g., MSG_rxSnr, MSG_rxRssi, MSG_hopStart, MSG_hopLimit, MSG_viaMqtt, etc.)
80518053
* - PARAM_*: Extracted parameters from trigger pattern
80528054
*/
8053-
private async createScriptEnvVariables(message: TextMessage, matchedPattern: string, extractedParams: Record<string, string>, trigger: AutoResponderTrigger, packetId?: number) {
8055+
private async createScriptEnvVariables(
8056+
message: TextMessage,
8057+
matchedPattern: string,
8058+
extractedParams: Record<string, string>,
8059+
trigger: AutoResponderTrigger,
8060+
packetId?: number,
8061+
context?: { nodeId: string; hopsTraveled: number; isDirectMessage: boolean }
8062+
) {
80548063
const config = await this.getScriptConnectionConfig();
80558064
const scriptEnv: Record<string, string> = {
80568065
...process.env as Record<string, string>,
@@ -8063,15 +8072,32 @@ class MeshtasticManager {
80638072
MESHTASTIC_PORT: String(config.tcpPort),
80648073
};
80658074

8075+
// Add token-matching environment variables (Issue #2314)
8076+
// These match the {TOKEN} names from the auto responder documentation
8077+
if (context) {
8078+
scriptEnv.NODE_ID = context.nodeId;
8079+
scriptEnv.HOPS = String(context.hopsTraveled);
8080+
scriptEnv.IS_DIRECT = String(context.isDirectMessage);
8081+
}
8082+
if (message.rxSnr !== undefined) scriptEnv.SNR = String(message.rxSnr);
8083+
if (message.rxRssi !== undefined) scriptEnv.RSSI = String(message.rxRssi);
8084+
scriptEnv.CHANNEL = String(message.channel);
8085+
scriptEnv.VIA_MQTT = String(message.viaMqtt);
8086+
80668087
// Add sender node information environment variables
80678088
const fromNode = await databaseService.nodes.getNode(message.fromNodeNum);
80688089
if (fromNode) {
80698090
// Add node names (Issue #1099)
80708091
if (fromNode.shortName) {
80718092
scriptEnv.FROM_SHORT_NAME = fromNode.shortName;
8093+
scriptEnv.SHORT_NAME = fromNode.shortName;
80728094
}
80738095
if (fromNode.longName) {
80748096
scriptEnv.FROM_LONG_NAME = fromNode.longName;
8097+
scriptEnv.LONG_NAME = fromNode.longName;
8098+
}
8099+
if (fromNode.firmwareVersion) {
8100+
scriptEnv.VERSION = fromNode.firmwareVersion;
80758101
}
80768102
// Add location (FROM_LAT, FROM_LON)
80778103
if (fromNode.latitude != null && fromNode.longitude != null) {
@@ -8080,6 +8106,12 @@ class MeshtasticManager {
80808106
}
80818107
}
80828108

8109+
// Add NODECOUNT - active nodes based on maxNodeAgeHours setting
8110+
const maxNodeAgeHours = parseInt(await databaseService.settings.getSetting('maxNodeAgeHours') || '24');
8111+
const maxNodeAgeDays = maxNodeAgeHours / 24;
8112+
const activeNodes = await databaseService.nodes.getActiveNodes(maxNodeAgeDays);
8113+
scriptEnv.NODECOUNT = String(activeNodes.length);
8114+
80838115
// Add location environment variables for the MeshMonitor node (MM_LAT, MM_LON)
80848116
const localNodeInfo = this.getLocalNodeInfo();
80858117
if (localNodeInfo) {

0 commit comments

Comments
 (0)