Skip to main content

Automatic Capture

The Anvil SDK automatically instruments all standard Control4 event handlers. Every time Control4 calls one of these functions, you'll see it in Anvil with the exact arguments that were passed.

How It Works

When you load the SDK, it registers wrappers for each C4 event handler:

-- Your code stays the same
function OnPropertyChanged(sProperty)
-- Do stuff
end

-- But now every call is captured with:
-- - The sProperty value
-- - How long your code took
-- - Any errors that occurred

You don't need to modify your handler implementations at all.

Agent Discovery

Capture is only active when the Anvil Agent is present on the controller. The SDK checks for it once Control4 has established bindings (in OnDriverLateInit):

  • Agent found. Anything captured during startup is delivered, and live streaming begins.
  • No agent. Startup capture is discarded and the SDK goes inert. Handler calls pass straight through to your code with no capture, no queuing, and no network activity, which is what makes it safe to ship the same build everywhere.

Events that fire before discovery completes are buffered in memory, capped at 500 (oldest dropped first). If the agent is installed after your driver loads, the SDK detects it and starts capturing from that moment on.

What You See

For each event, Anvil shows:

The handler name:

OnPropertyChanged

The arguments Control4 passed, matched to your parameter names where Lua's introspection allows (positional otherwise):

sProperty: "Volume"

The return values from your handler, including multiple returns.

Timing:

Duration: 3ms

And if something broke, the full error:

ERROR: attempt to index nil value
driver.lua:142: in function <OnPropertyChanged>

Error stack traces include the value of every local variable in every frame at the moment of the error, so you can see exactly what your code was working with when it failed. Long values are bounded: strings truncate at 512 characters, and tables are capped in depth and size.

Sensitive Data

The SDK doesn't scan for or redact sensitive-looking values, so what your handler receives is what appears in Anvil. The exception is GetPrivateKeyPassword: the SDK records that the handler fired, but replaces its arguments with [REDACTED] and withholds its return value.

Captured Handlers

The SDK instruments 157 handlers across all Control4 event categories. Here's the complete list:

Command & Action Handlers

HandlerWhen It Fires
ExecuteCommandCommand sent to your driver
ExecuteActionAction triggered

Data & Communication Handlers

HandlerWhen It Fires
OnDataFromUIData received from UI
OnDataToUIData being sent to UI
GetPrivateKeyPasswordPrivate key password requested
UIRequestUI request from navigator
ReceivedAsyncAsync response received
ReceivedFromProxyData from a proxy binding

Driver Lifecycle Handlers

HandlerWhen It Fires
OnDriverInitDriver is initializing
OnDriverLateInitAfter bindings are established
OnDriverUpdateDriver is being updated
OnDriverDestroyedDriver is being unloaded
OnDriverAddedNew driver added to project
OnDriverDisabledDriver was disabled
OnAlivePeriodic health check

Connection & Network Handlers

HandlerWhen It Fires
OnConnectionStatusChangedConnection state changed
OnServerConnectionStatusChangedServer connection changed
OnNetworkBindingChangedNetwork binding changed
OnConnectionAuthorizedConnection authorized
ReceivedFromNetworkNetwork data received
ReceivedFromSerialSerial data received
OnAuthorizedConnectionDisconnectedAuthorized connection lost
OnNetworkBindingStatusChangedNetwork binding status changed

Device Handlers

HandlerWhen It Fires
OnDeviceEventDevice-specific event
OnDeviceOnlineDevice came online
OnDeviceOfflineDevice went offline
OnDeviceDiscoveredDevice discovered
OnDeviceIdentifiedDevice identified
OnDeviceIdentifyingDevice identification in progress
OnDevicePreIdentifyBefore device identification
OnDeviceIPAddressChangedDevice IP changed
OnDeviceFirmwareChangedDevice firmware updated
OnDeviceDataChangedDevice data modified
OnDeviceUserInitiatedRemoveUser initiated device removal
OnDeviceAlreadyIdentifiedDevice was already identified
OnDeviceCancelIdentifyDevice identification cancelled
OnDeviceIdentifiedNoLicenseDevice identified but no license
OnPhysicalDeviceAddedPhysical device added
OnPhysicalDeviceRemovedPhysical device removed
OnDiscoveredDeviceAddedDiscovered device added
OnDiscoveredDeviceChangedDiscovered device changed
OnDiscoveredDeviceRemovedDiscovered device removed
OnSearchTypeFoundSearch type found

Event & Timer Handlers

HandlerWhen It Fires
OnEventFiredEvent fired
OnTimerExpiredLegacy timer fired
OnScheduledEventScheduled event triggered
OnSystemEventSystem-wide event
OnEventAddedEvent added
OnEventRemovedEvent removed
OnEventModifiedEvent modified
OnWatchedVariableChangedWatched variable changed
OnAllCatch-all handler

Property & Variable Handlers

HandlerWhen It Fires
OnPropertyChangedProperty value changed
OnProjectPropertyChangedProject property changed
OnVariableChangedVariable value changed
OnVariableAddedVariable created
OnVariableRemovedVariable deleted
OnVariableRenamedVariable renamed
OnUserVariableAddedUser variable added
OnItemDataChangedItem data changed
OnAccessModeChangedAccess mode changed
OnTimeChangedSystem time changed
OnLatitudeChangedLatitude changed
OnLongitudeChangedLongitude changed

Binding Handlers

HandlerWhen It Fires
OnBindingChangedBinding connection changed
OnBindingAddedNew binding created
OnBindingRemovedBinding removed
OnBindingEntryAddedBinding entry added
OnBindingEntryRemovedBinding entry removed
OnBindingEntryRenamedBinding entry renamed
OnVariableBindingAddedVariable binding added
OnVariableBindingRemovedVariable binding removed
OnVariableBindingRenamedVariable binding renamed
OnVariableAddedToBindingVariable added to binding
OnVariableRemovedFromBindingVariable removed from binding
OnNetworkBindingAddedNetwork binding added
OnNetworkBindingRemovedNetwork binding removed

Network Binding Handlers

HandlerWhen It Fires
OnNetworkBindingRegisteredNetwork binding registered
OnNetworkBindingUnregisteredNetwork binding unregistered
OnNetworkBindingAddressChangedNetwork binding address changed
OnCIDRRulesChangedCIDR rules changed
OnDirectorIPAddressChangedDirector IP changed

Project Handlers

HandlerWhen It Fires
OnProjectLoadedProject loaded
OnProjectLoadingProject loading
OnProjectNewNew project created
OnProjectChangedProject changed
OnProjectLockedProject locked
OnProjectEnterLockEntering project lock
OnProjectLeaveLockLeaving project lock
OnProjectClearProject cleared
OnLocaleChangedLocale changed

Server Handlers

HandlerWhen It Fires
OnServerStatusChangedServer status changed
OnServerDataInServer data received
OnSDDPDeviceStatusSDDP device status update

Media Session Handlers

HandlerWhen It Fires
OnMediaSessionAddedMedia session added
OnMediaSessionRemovedMedia session removed
OnMediaSessionChangedMedia session changed
OnMediaSessionVolumeLevelChangedVolume level changed
OnMediaSessionVolumeSliderStateChangedVolume slider state changed
OnMediaSessionMuteStateChangedMute state changed
OnMediaSessionDiscreteMuteChangedDiscrete mute changed
OnMediaSessionDiscreteVolumeChangedDiscrete volume changed
OnMediaSessionSliderTargetVolumeReachedSlider target volume reached

Media Device Handlers

HandlerWhen It Fires
OnMediaDeviceAddedMedia device added
OnMediaDeviceRemovedMedia device removed
OnMediaDeviceChangedMedia device changed
OnMediaInfoAddedMedia info added
OnMediaInfoModifiedMedia info modified
OnMediaRemovedFromDeviceMedia removed from device

Media & Playlist Handlers

HandlerWhen It Fires
OnSongAddedToPlaylistSong added to playlist
OnSongRemovedFromPlaylistSong removed from playlist
OnMediaDataRemovedMedia data removed
OnMediaSessionMediaInfoChangedSession media info changed

Item Handlers

HandlerWhen It Fires
OnItemAddedItem added
OnItemMovedItem moved
OnItemNameChangedItem name changed
OnItemRemovedItem removed

Code Item Handlers

HandlerWhen It Fires
OnCodeItemAddedCode item added
OnCodeItemRemovedCode item removed
OnCodeItemMovedCode item moved
OnCodeItemEnabledCode item enabled
OnCodeItemCommandUpdatedCode item command updated
OnCodeItemAddedToExpressionCode item added to expression

Zigbee Handlers

HandlerWhen It Fires
OnZigbeeNodeOfflineZigbee node went offline
OnZigbeeNodeOnlineZigbee node came online
OnZigbeeNodesChangedZigbee nodes changed
OnZigbeeMeshChangedZigbee mesh changed
OnZigbeeDuplicateMeshDuplicate Zigbee mesh detected
OnZigbeeNetworkHealthZigbee network health update
OnZigbeeNodeUpdateStatusNode update status
OnZigbeeNodeUpdateSucceededNode update succeeded
OnZigbeeNodeUpdateFailedNode update failed
OnZigbeeZserverChangedZserver changed
OnZigbeeZapsChangedZaps changed
OnZigBeeStickPresentZigbee stick present
OnZigBeeStickRemovedZigbee stick removed

System Update & Discovery Handlers

HandlerWhen It Fires
OnSystemUpdateStartedSystem update started
OnSystemUpdateFinishedSystem update finished
OnSystemShutDownSystem shutting down
OnSDDPDeviceDiscoverSDDP device discovered
OnSysmanResponseSysman response received
OnReflashLockGrantedReflash lock granted
OnReflashLockRevokedReflash lock revoked
OnControllerDisabledController disabled

Notification Handlers

HandlerWhen It Fires
GetNotificationAttachmentURLGet notification attachment URL
GetNotificationAttachmentFileGet notification attachment file
GetNotificationAttachmentBytesGet notification attachment bytes
FinishedWithNotificationAttachmentNotification attachment finished

List Handlers

HandlerWhen It Fires
ListMIBReceivedMIB list received
ListNewControlNew control list
ListEventList event
ListNewListNew list created

Other Handlers

HandlerWhen It Fires
OnZipcodeChangedZipcode changed
OnPIPPIP event
OnTimezoneChangedTimezone changed

What's NOT Captured

Due to Lua limitations with protected userdata, these require manual capture:

  • C4:SetTimer() callbacks
  • C4:url():OnDone() callbacks
  • Other async callbacks passed to C4 methods

The SDK can't wrap these automatically, but provides simple APIs to capture them.