Intrusion Events
Overview
Intrusion events cover all perimeter and zone-based detections: someone entering a defined zone, crossing a tripwire, loitering, or parking illegally. All intrusion events have category == "intrusion".
The SDK routes these events through ViewtronEvent() like any other category. Your on_event callback receives the parsed object with all common methods available.
Event Types
Multiple classes handle intrusion events. IPC cameras (v1.x) and NVRs (v2.0) use different smartType values and XML structures, but the SDK gives them the same interface.
IPC v1.x Classes
| Class | smartType | Description |
|---|---|---|
IntrusionDetection | PEA | Perimeter intrusion — someone enters a defined zone, or crosses a tripwire |
IntrusionEntry | AOIENTRY | Area of interest — entry into a zone |
IntrusionExit | AOILEAVE | Area of interest — exit from a zone |
LoiteringDetection | LOITER | Person loitering in a zone beyond a time threshold |
IllegalParking | PVD | Parking violation detection |
PEA handles both intrusion zones and tripwire line crossings on IPC cameras. The XML contains either a \<perimeter> block (zone intrusion) or a \<tripwire> block (line crossing), but the SDK class is the same.
NVR v2.0 Classes
| Class | smartType | Description |
|---|---|---|
RegionIntrusion | regionIntrusion | Perimeter / zone intrusion |
LineCrossing | lineCrossing | Tripwire / line crossing |
NVR v2.0 separates intrusion and line crossing into distinct smartTypes, unlike IPC which uses PEA for both.
Common Properties
All intrusion event objects share these methods. IPC classes inherit from APIpost; NVR classes inherit from APIpostV2. The interface is the same.
| Method | Returns | Description |
|---|---|---|
get_alarm_type() | str | Raw smartType value (e.g., "PEA", "regionIntrusion", "lineCrossing") |
get_alarm_description() | str | Human-readable name (e.g., "Line Crossing / Intrusion", "Perimeter Intrusion") |
get_target_types() | dict | IPC only — target type mapping from the camera (e.g., "1,2,4" = person, car, bike) |
get_ip_cam() | str | Camera device name |
get_time_stamp_formatted() | str | Formatted timestamp (e.g., "2026-04-09 15:30:45") |
get_time_stamp() | str | Unix timestamp as string, for use in filenames |
source_image_exists() | bool | True if an overview/scene image is included |
target_image_exists() | bool | True if a target crop image is included |
get_source_image_bytes() | bytes or None | Overview image as decoded JPEG bytes |
get_target_image_bytes() | bytes or None | Target crop as decoded JPEG bytes |
get_channel_id() | str | NVR v2.0 only — channel number (e.g., "1") |
Alarm Description Values
| smartType | get_alarm_description() returns |
|---|---|
PEA | "Line Crossing / Intrusion" |
AOIENTRY | "Intrusion Zone Entry" |
AOILEAVE | "Intrusion Zone Exit" |
LOITER | "Loitering Detection" |
PVD | "Illegal Parking" |
regionIntrusion | "Perimeter Intrusion" |
lineCrossing | "Line Crossing" |
IPC vs NVR Comparison
| Feature | IPC v1.x | NVR v2.0 |
|---|---|---|
| Alarm types | PEA, AOIENTRY, AOILEAVE, LOITER, PVD | regionIntrusion, lineCrossing |
| Target type | Numeric ID in XML — 1=person, 2=car, 4=bike | String in targetListInfo — "person", "car" |
| Event ID | In \<perimeter> / \<tripwire> XML block | In \<eventInfo> block |
| Status | SMART_START, PROCEDURE, SMART_STOP | Not used |
| Boundary type | Implicit — \<perimeter> or \<tripwire> block present | Explicit — "area" or "tripwire" in eventInfo |
| Channel ID | Not available | get_channel_id() returns channel number |
| Device IP / MAC | Not available | Parsed from \<deviceInfo> |
Note on status: IPC v1.x events include a status field in the raw XML (SMART_START when the detection begins, PROCEDURE while ongoing, SMART_STOP when it ends). The SDK does not expose this as a method — it is available in the raw XML if you need it.
Code Examples
Basic Intrusion Handling
from viewtron import ViewtronServer
def handle_event(event, client_ip):
if event.category == "intrusion":
alarm = event.get_alarm_description()
camera = event.get_ip_cam()
timestamp = event.get_time_stamp_formatted()
print(f"[{timestamp}] {alarm} on {camera}")
server = ViewtronServer(port=5050, on_event=handle_event)
server.serve_forever()
Filtering by Alarm Type
def handle_event(event, client_ip):
if event.category == "intrusion":
alarm_type = event.get_alarm_type()
if alarm_type in ("PEA", "regionIntrusion"):
print("Zone intrusion detected")
elif alarm_type == "lineCrossing":
print("Line crossing detected")
elif alarm_type == "LOITER":
print("Loitering detected")
elif alarm_type == "AOIENTRY":
print("Zone entry detected")
elif alarm_type == "AOILEAVE":
print("Zone exit detected")
elif alarm_type == "PVD":
print("Illegal parking detected")
Saving Images
def handle_event(event, client_ip):
if event.category == "intrusion":
if event.source_image_exists():
timestamp = event.get_time_stamp()
with open(f"intrusion_{timestamp}.jpg", "wb") as f:
f.write(event.get_source_image_bytes())
if event.target_image_exists():
timestamp = event.get_time_stamp()
with open(f"intrusion_target_{timestamp}.jpg", "wb") as f:
f.write(event.get_target_image_bytes())
Combined with Other Event Types
def handle_event(event, client_ip):
if event.category == "lpr":
print(f"Plate: {event.get_plate_number()}")
elif event.category == "intrusion":
print(f"Intrusion: {event.get_alarm_description()}")
elif event.category == "face":
print(f"Face detected")
Related Pages
- ViewtronEvent — common properties and category routing
- Images — working with event images
- API Reference: Intrusion/Perimeter Detection — raw XML endpoint documentation, detection zone configuration