notifybuildresult
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.
Features
- 🚀 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
Use Cases
- 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
Installation
- Open VS Code
- Press
Ctrl+P (Windows/Linux) or Cmd+P (macOS)
- Type
ext install sdrshnptl.notifybuildresult
- Press Enter
Or install from Marketplace:
VS Code Marketplace - notifybuildresult
Quick Start
Basic Setup
- 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}
ESP-IDF Example
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
}
Configuration
Settings Reference
| 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 |
Message Templates
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
Output-Based Filtering
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).
Commands
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
Examples
Example 1: Simple Build Notifications
{
"notifybuildresult.enabled": true,
"notifybuildresult.successMessage": "{\"build\":\"success\"}",
"notifybuildresult.failureMessage": "{\"build\":\"failed\"}"
}
Example 2: ESP32 RGB LED Control
{
"notifybuildresult.taskFilter": ["ESP-IDF", "build"],
"notifybuildresult.successMessage": "{\"led\":{\"r\":0,\"g\":255,\"b\":0}}",
"notifybuildresult.failureMessage": "{\"led\":{\"r\":255,\"g\":0,\"b\":0}}"
}
Example 3: Detailed Status with Templates
{
"notifybuildresult.useMessageTemplate": true,
"notifybuildresult.successTemplate": "{\"project\":\"${workspaceFolder}\",\"task\":\"${taskName}\",\"status\":\"OK\",\"time\":\"${timestamp}\"}",
"notifybuildresult.failureTemplate": "{\"project\":\"${workspaceFolder}\",\"task\":\"${taskName}\",\"status\":\"ERROR\",\"time\":\"${timestamp}\"}"
}
Receiving UDP Broadcasts
Python Receiver Example
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}")
Node.js Receiver Example
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...');
});
ESP32 Receiver Example (Arduino/ESP-IDF)
#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);
}
}
}
Troubleshooting
Broadcasts Not Received
- 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.1 for local testing
Extension Not Detecting Tasks
- Enable diagnostic logging: Set
notifybuildresult.logToOutput to true (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.enabled should be true
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}
Only Specific Tasks Should Trigger
Use the taskFilter setting:
{
"notifybuildresult.taskFilter": ["build", "compile", "ESP-IDF"]
}
Task names are matched case-insensitively with substring matching.
Messages Not Valid JSON
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.
Development
# 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 publish
Contributing
Issues and pull requests are welcome at:
https://github.com/sdrshnptl/notifybuildresult
License
MIT