How Webhook Event Notifications Are Triggered for Motion Detection and Recording in AtomCam Tools
AtomCam Tools triggers webhook event notifications by piping specially-formatted log lines to a FIFO file (/var/run/atomapp), where an awk script parses motion detection, recording, and timelapse events and POSTs JSON payloads to a configured URL via curl.
The mnakada/atomcam_tools repository implements a lightweight, log-driven notification system that keeps the core camera firmware decoupled from networking logic. Instead of direct HTTP calls from C components, the system writes tagged messages to a named pipe and relies on overlay_rootfs/scripts/webhook.sh to dispatch alarmEvent, recordEvent, and timelapseEvent notifications when enabled in the configuration.
Motion Detection Webhook Notifications
Motion detection events originate from either the hardware motion sensor or the onboard AI algorithm. When triggered, these components write specific log patterns to the FIFO that webhook.sh monitors.
Log Pattern Matching
The awk script in overlay_rootfs/scripts/webhook.sh listens for three distinct regex patterns to identify motion alarms:
/\[aiAlgo\] start/ {
if(ENV["WEBHOOK_ALARM_EVENT"] == "on") Post("alarmEvent");
}
/alarm_event_handle.*timestamp/ {
if(ENV["WEBHOOK_ALARM_EVENT"] == "on") Post("alarmEvent");
}
/(alarm_event_handle).*== readly to alarm ==/ {
if(ENV["WEBHOOK_ALARM_EVENT"] == "on") Post("alarmEvent");
}
When any pattern matches and WEBHOOK_ALARM_EVENT is set to "on", the script invokes the internal Post() function.
JSON Payload Construction
The Post() function constructs a minimal JSON object and dispatches it via curl:
system("curl -X POST -m 3 -H 'Content-Type: application/json' \
-d '{\"type\":\"alarmEvent\", \"device\":\"" HOSTNAME "\"}' \
" INSECURE_FLAG ENV["WEBHOOK_URL"] " > /dev/null 2>&1")
The resulting payload sent to the webhook URL is:
{"type":"alarmEvent", "device":"my-atomcam"}
Recording Finish Webhook Notifications
Regular recordings generate notifications through a different path. When a one-minute recording segment completes, the atom_patch/bin/mv helper handles file movement from temporary storage to /media/mmc/record/.
Trigger Condition in the Move Helper
After successfully moving the MP4 file, the mv script checks environment variables before dispatching:
if [ "$WEBHOOK_URL" != "" ] && [ "$WEBHOOK_RECORD_EVENT" = "on" ]; then
LD_LIBRARY_PATH=/tmp/system/lib:/tmp/system/usr/lib \
/tmp/system/lib/ld.so.1 /tmp/system/bin/curl -X POST -m 3 \
-H "Content-Type: application/json" \
-d "{\"type\":\"recordEvent\", \"device\":\"${HOSTNAME}\"${STORAGE}}" \
$INSECURE_FLAG $WEBHOOK_URL > /dev/null 2>&1
fi
The STORAGE variable appends optional file location metadata (sdcardFile or cifsFile) to the payload, allowing the receiver to locate the saved video immediately.
Timelapse Webhook Notifications
Timelapse events are generated directly from the C library libcallback/timelapse.c. The code prints specially-formatted strings to stdout that travel through the same FIFO pipeline.
Event Emission in timelapse.c
The timelapse module emits status updates using printf statements:
printf("[webhook] time_lapse_event %s %d/%d %d\n",
ProcessingInfo.mp4File,
ProcessingInfo.count,
ProcessingInfo.numOfTimes,
ScheduleNo);
printf("[webhook] time_lapse_finish %s %d/%d %d\n", ...);
awk Processing
In webhook.sh, lines 88-91 capture these tags:
/\[webhook\] time_lapse_event/ {
if(ENV["WEBHOOK_TIMELAPSE_EVENT"] == "on")
Post("timelapseEvent", "\"" $0 "\"");
}
The payload includes the raw log line containing the file path and progress counters, enabling external systems to track timelapse completion status.
Configuration and Enablement
All webhook behavior is controlled via environment variables stored in /tmp/hack.ini. The Web UI (web/source/vue/Setting.vue) exposes toggles for each event type:
<SettingSwitch i18n="event.webhook.alarm" v-model="config.WEBHOOK_ALARM_EVENT" />
<SettingSwitch i18n="event.webhook.recordingSave" v-model="config.WEBHOOK_RECORD_EVENT" />
When a user enables a switch, the corresponding WEBHOOK_ALARM_EVENT, WEBHOOK_RECORD_EVENT, or WEBHOOK_TIMELAPSE_EVENT variable is set to "on". The webhook.sh script reads these variables at startup and applies them to its pattern matching logic.
Summary
- Motion detection triggers
alarmEventwebhooks whenalarm_event_handleor[aiAlgo] startpatterns appear in the FIFO andWEBHOOK_ALARM_EVENTis enabled. - Recording completion triggers
recordEventwebhooks via theatom_patch/bin/mvhelper whenWEBHOOK_RECORD_EVENTis set to"on". - Timelapse progress triggers
timelapseEventwebhooks fromlibcallback/timelapse.cwhenWEBHOOK_TIMELAPSE_EVENTis active. - All notifications are dispatched by
overlay_rootfs/scripts/webhook.shusing curl to the URL defined inWEBHOOK_URL. - Configuration persists in
hack.iniand is managed through the Vue-based Web UI settings panel.
Frequently Asked Questions
What URL format does AtomCam Tools expect for webhooks?
The system expects a standard HTTP or HTTPS URL assigned to the WEBHOOK_URL environment variable. The curl command in webhook.sh appends this URL directly to the POST request without additional path manipulation, so the endpoint should be prepared to receive POST requests at the root of the provided address.
Can I receive the actual file path in the recording webhook?
Yes. When WEBHOOK_RECORD_EVENT is enabled, the atom_patch/bin/mv helper appends a STORAGE variable to the JSON payload containing either "sdcardFile":"/path/to/file" or "cifsFile":"/path/to/file" depending on where the MP4 was saved. Parse the recordEvent payload to extract the location.
Why does the motion detection use three different regex patterns?
The three patterns—alarm_event_handle.*timestamp, alarm_event_handle.*== readly to alarm ==, and \[aiAlgo\] start—cover different firmware paths. The hardware motion detector and AI algorithm write slightly different log formats to /var/run/atomapp. The awk script in webhook.sh watches for all three to ensure reliable detection regardless of which subsystem triggered the alarm.
Is there a way to test webhooks without waiting for actual motion?
You can manually write to the FIFO pipe to simulate events. As root, execute echo "alarm_event_handle test timestamp" > /var/run/atomapp while webhook.sh is running with WEBHOOK_ALARM_EVENT=on. This forces the awk script to match the pattern and dispatch a test alarmEvent to your configured URL.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →