Broadcast UDP messages on task completion to trigger external devices and systems
A VS Code extension that sends UDP broadcast messages when tasks complete, enabling you to trigger external devices like RGB LEDs, displays, IoT devices, or automation systems based on build results.
- 🚀 Automatic Broadcasts - Send UDP messages when VS Code tasks complete (build success/failure)
- 🎯 Task Filtering - Only broadcast for specific tasks (e.g., ESP-IDF builds)
- 📝 Configurable Messages - Customize success and failure messages
- 🔧 Message Templates - Use variables like task name, timestamp, workspace folder
- 📊 Status Bar Integration - See broadcast status at a glance
- 📜 Broadcast History - View last 20 broadcasts
- 🧪 Connection Testing - Test your UDP configuration easily
- 📤 Manual Trigger - Send broadcasts manually via command palette
- 🔍 Output Filtering - Trigger broadcasts based on task output content (e.g., ESP-IDF build logs)
- 🐛 Diagnostic Logging - Detailed logs to troubleshoot task detection
- ESP-IDF Development: Trigger RGB LEDs or displays on ESP32 build completion
- IoT Integration: Notify smart home devices about build status
- Team Notifications: Broadcast to office status lights or displays
- CI/CD Integration: Trigger external automation systems
- Custom Workflows: Integrate VS Code with any UDP-listening device
- Open VS Code
- Press
Ctrl+P(Windows/Linux) orCmd+P(macOS) - Type
ext install sdrshnptl.notifybuildresult - Press Enter
Or install from Marketplace: VS Code Marketplace - notifybuildresult
- Open VS Code Settings (
Ctrl+,) - Search for "notifybuildresult"
- Configure:
- Broadcast Address:
255.255.255.255(network-wide) or specific IP - Port:
10203(default) - Success Message:
{"compile":1} - Failure Message:
{"error":1}
- Broadcast Address:
For ESP-IDF projects, filter only build tasks:
{
"notifybuildresult.enabled": true,
"notifybuildresult.taskFilter": ["ESP-IDF"],
"notifybuildresult.successMessage": "{\"compile\":1}",
"notifybuildresult.failureMessage": "{\"error\":1}",
"notifybuildresult.broadcastAddress": "255.255.255.255",
"notifybuildresult.port": 10203
}| Setting | Type | Default | Description |
|---|---|---|---|
notifybuildresult.enabled |
boolean | true |
Enable/disable broadcasts |
notifybuildresult.broadcastAddress |
string | 255.255.255.255 |
Target IP address |
notifybuildresult.port |
number | 10203 |
UDP port number |
notifybuildresult.successMessage |
string | {"compile":1} |
Message for successful tasks |
notifybuildresult.failureMessage |
string | {"error":1} |
Message for failed tasks |
notifybuildresult.taskFilter |
array | [] |
Filter tasks by name (empty = all tasks) |
notifybuildresult.useMessageTemplate |
boolean | false |
Enable template variables |
notifybuildresult.successTemplate |
string | See below | Template for success |
notifybuildresult.failureTemplate |
string | See below | Template for failure |
notifybuildresult.showStatusBar |
boolean | true |
Show status bar indicator |
notifybuildresult.logToOutput |
boolean | true |
Log activity to output channel |
notifybuildresult.enableOutputFiltering |
boolean | false |
Enable output-based triggering |
notifybuildresult.successTriggerStrings |
array | ESP-IDF patterns | Strings to detect success in output |
notifybuildresult.failureTriggerStrings |
array | Build error patterns | Strings to detect failure in output |
Enable advanced templates with variables:
{
"notifybuildresult.useMessageTemplate": true,
"notifybuildresult.successTemplate": "{\"status\":\"success\",\"task\":\"${taskName}\",\"time\":\"${timestamp}\"}",
"notifybuildresult.failureTemplate": "{\"status\":\"error\",\"task\":\"${taskName}\",\"time\":\"${timestamp}\"}"
}Available Variables:
${taskName}- Name of the completed task${timestamp}- ISO 8601 timestamp${workspaceFolder}- Workspace folder name${workspacePath}- Full workspace path
For build systems where exit codes don't reliably indicate success/failure, use output filtering:
{
"notifybuildresult.enableOutputFiltering": true,
"notifybuildresult.successTriggerStrings": [
"Successfully created",
"Generated ",
"binary size",
"bytes free",
"0 errors",
"build complete"
],
"notifybuildresult.failureTriggerStrings": [
"FAILED",
"ninja: build stopped",
"error:",
"fatal error",
"undefined reference",
"CMake Error"
]
}Default Trigger Strings:
The extension comes pre-configured with ESP-IDF-friendly trigger strings:
- Success patterns:
"Successfully created","Generated ","binary size","bytes free","0 errors","build complete" - Failure patterns:
"FAILED","ninja: build stopped","error:","fatal error","undefined reference","CMake Error"
When output filtering is enabled but no task output is captured, the extension automatically falls back to exit-code detection (exit code 0 = success).
Access via Command Palette (Ctrl+Shift+P):
- notifybuildresult: Send Manual Message - Send custom UDP message
- notifybuildresult: Test Connection - Test your UDP configuration
- notifybuildresult: Show History - View broadcast history
{
"notifybuildresult.enabled": true,
"notifybuildresult.successMessage": "{\"build\":\"success\"}",
"notifybuildresult.failureMessage": "{\"build\":\"failed\"}"
}{
"notifybuildresult.taskFilter": ["ESP-IDF", "build"],
"notifybuildresult.successMessage": "{\"led\":{\"r\":0,\"g\":255,\"b\":0}}",
"notifybuildresult.failureMessage": "{\"led\":{\"r\":255,\"g\":0,\"b\":0}}"
}{
"notifybuildresult.useMessageTemplate": true,
"notifybuildresult.successTemplate": "{\"project\":\"${workspaceFolder}\",\"task\":\"${taskName}\",\"status\":\"OK\",\"time\":\"${timestamp}\"}",
"notifybuildresult.failureTemplate": "{\"project\":\"${workspaceFolder}\",\"task\":\"${taskName}\",\"status\":\"ERROR\",\"time\":\"${timestamp}\"}"
}import socket
import json
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 10203))
print("Listening for UDP broadcasts on port 10203...")
while True:
data, addr = sock.recvfrom(1024)
message = json.loads(data.decode())
print(f"Received from {addr}: {message}")const dgram = require('dgram');
const server = dgram.createSocket('udp4');
server.on('message', (msg, rinfo) => {
const data = JSON.parse(msg.toString());
console.log(`Received: ${JSON.stringify(data)} from ${rinfo.address}:${rinfo.port}`);
});
server.bind(10203, () => {
console.log('Listening for UDP broadcasts on port 10203...');
});#include <WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
WiFiUDP udp;
const int UDP_PORT = 10203;
void setup() {
Serial.begin(115200);
WiFi.begin("YOUR_SSID", "YOUR_PASSWORD");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
udp.begin(UDP_PORT);
}
void loop() {
int packetSize = udp.parsePacket();
if (packetSize) {
char packet[255];
int len = udp.read(packet, 255);
packet[len] = 0;
StaticJsonDocument<200> doc;
deserializeJson(doc, packet);
if (doc["compile"] == 1) {
// Green LED for success
digitalWrite(LED_GREEN, HIGH);
} else if (doc["error"] == 1) {
// Red LED for error
digitalWrite(LED_RED, HIGH);
}
}
}- Check firewall settings - Allow UDP on your port (default: 10203)
- Verify network configuration - Ensure broadcast is enabled on your network
- Test connection: Run the command "notifybuildresult: Test Connection"
- Check output channel - View → Output → "UDP Broadcast" for diagnostic logs
- Try loopback: Set broadcast address to
127.0.0.1for local testing
- Enable diagnostic logging: Set
notifybuildresult.logToOutputtotrue(enabled by default) - Open the output channel: View → Output → Select "UDP Broadcast" from dropdown
- Run your task and look for diagnostic messages:
[TASK START]- Shows task name, type, and ID when task starts[TASK END]- Shows task name, exit code, and enabled status when task completes[FILTER CHECK]- Shows whether task passed filter checks
- Verify task filter: If set, ensure your task name matches the filter
- Check if extension is enabled:
notifybuildresult.enabledshould betrue
Example Diagnostic Output:
[10:30:45] [TASK START] Task: "ESP-IDF Build", Type: shell, ID: ESP-IDF Build-1709025045123
[10:30:48] [TASK END] Task: "ESP-IDF Build", Exit Code: 0, Enabled: true
[10:30:48] [FILTER CHECK] No task filter set, broadcasting for all tasks
[10:30:48] Task "ESP-IDF Build" succeeded - Broadcasting message
[10:30:48] ✓ Broadcast sent: {"compile":1}
Use the taskFilter setting:
{
"notifybuildresult.taskFilter": ["build", "compile", "ESP-IDF"]
}Task names are matched case-insensitively with substring matching.
If you're using plain text messages, that's fine - receivers will get the raw string. For JSON:
{
"notifybuildresult.successMessage": "{\"key\":\"value\"}"
}Note: Backslashes escape quotes in JSON configuration.
# Install dependencies
npm install
# Compile TypeScript
npm run compile
# Watch mode for development
npm run watch
# Package extension
npx @vscode/vsce package
# Publish to marketplace
npx @vscode/vsce publishIssues and pull requests are welcome at: https://github.com/sdrshnptl/notifybuildresult
MIT