Skip to main content

Viewtron Python SDK

Python SDK for Viewtron IP camera API. Parse inbound alarm events and control cameras programmatically.

Viewtron IP cameras run AI detection on-camera (license plate recognition, face detection, human/vehicle detection) and send HTTP POST events to your server. This SDK parses those events and provides an API client for camera control.

Version 1.4.0 adds API 2.1 support for the Viewtron LPR-IP4 license plate recognition camera (firmware 5.3.x): plate direction (approach / away), confidence, allow / block / temporary plate lists by name, vehicle color, type, brand and model, capability discovery, and an on_unparsed hook for posts the SDK does not recognize.

Install

pip install viewtron

Inbound Events — Parse Camera Alarm Data

Viewtron cameras and NVRs send XML alarm events via HTTP POST. This SDK parses them into Python objects.

from viewtron import ViewtronServer

def on_event(event, client_ip):
    if event.category == "lpr":
        print(event.get_plate_number())       # "IB36NL"
        print(event.get_plate_group())        # "whiteList" or NVR group name
        print(event.direction)                # "approach", "away", or None
        print(event.confidence)               # 0-100, e.g. 99.0
        print(event.plate_list)               # "whiteList" or None
        print(event.vehicle_color, event.vehicle_brand, event.vehicle_type)

        # Images as decoded JPEG bytes — ready for saving, MQTT, notifications
        overview = event.get_source_image_bytes()   # full scene
        plate_crop = event.get_target_image_bytes() # plate closeup

def on_unparsed(xml, client_ip, reason):
    # reason is unknown-smartType, no-messageType, parse-error, or alarmStatus
    print(reason, client_ip)

server = ViewtronServer(port=5050, on_event=on_event, on_unparsed=on_unparsed)
server.serve_forever()

Every parsed event has config_version (the post's config version, such as "1.7" or "2.1.0") and format ("v1" or "v2"). A version-2 post that uses an IPC smartType and has no messageType is parsed with the IPC classes. smartType matching ignores case when that is unambiguous. VEHICLE in a version-2 envelope is a plate event only when licensePlateListInfo is present; otherwise on_unparsed is called with unknown-smartType.

on_raw is unchanged. The server reads Transfer-Encoding: chunked bodies and does not treat them as keepalives.

On an LPR event, direction is "approach", "away", or None. A post that says leave is "away". confidence is a float from 0 to 100 (PlateConfidence count="9900" is 99.0) or None. plate_list is whiteList, blackList, temporaryList, strangerList, or None. vehicle_color, vehicle_brand, vehicle_type, and vehicle_model come from the plate item's vehicle attributes when the post includes them. get_plate_group() still returns the raw group text, including a custom NVR group name. get_time_stamp_formatted() is the camera's event time. currentTime may be seconds, milliseconds, or microseconds.

examples/gate_direction_filter.py acts only on approaching allow-list plates at 90% confidence or higher.

Every LPR field is documented in the license plate recognition camera API docs. For a real driveway or HOA gate setup, see our ALPR gate access control walkthrough.

Supported Event Types

Source Class Detection
IPC v1.x LPR License plate recognition with plate groups
IPC v1.x FaceDetection Face detection with crop image
IPC v1.x IntrusionDetection Perimeter intrusion (person/vehicle)
IPC v1.x IntrusionEntry Zone entry
IPC v1.x IntrusionExit Zone exit
IPC v1.x LoiteringDetection Loitering
IPC v1.x VideoMetadata Continuous object detection
NVR v2.0 VehicleLPR LPR with vehicle brand/color/type and plate groups
NVR v2.0 FaceDetectionV2 Face detection with age/sex/glasses/mask
NVR v2.0 RegionIntrusion Perimeter intrusion
NVR v2.0 LineCrossing Tripwire line crossing
NVR v2.0 TargetCountingByLine People/vehicle counting by line
NVR v2.0 TargetCountingByArea People/vehicle counting by area
NVR v2.0 VideoMetadataV2 Continuous object detection

Version detection is automatic. IPC v1.x and version-2 posts (2.0, 2.1, and later 2.x versions with the same layout) use different XML structures; the SDK handles both. Check event.format and event.config_version when you need to tell them apart.

Outbound API — Control the Camera

Viewtron cameras ship set to DHCP, so the camera gets its address from your router. Find it with our IP camera finder tool and use it in place of the example address below.

from viewtron import ViewtronCamera

camera = ViewtronCamera("192.168.0.20", "admin", "password")

# Device info
info = camera.get_device_info()
print(info["model"])  # "LPR-IP4"

# What this firmware supports
caps = camera.capabilities
print(caps.api_version, caps.http_post_version, caps.config_version)
print(caps.supported_apis)  # frozenset, or None when GetSupportedAPIs is unavailable

# Plate groups. On current firmware (a camera running 5.3.1, API 2.1.0)
# group 1 is temporaryList and the allow list is whiteList, typically group 2.
print(camera.get_plate_groups())  # {1: "temporaryList", 2: "whiteList", 3: "blackList"}

# Manage the license plate database. Pass group= so the id is resolved for you.
# Omitting it still uses group id "1" and warns once; that default changes in a future major release.
plates = camera.get_plates(group="whiteList")
camera.add_plate("IB36NL", group="allow")  # allow, block, and temporary also resolve
camera.modify_plate("IB36NL", owner="Mike", telephone="555-1234", group="whiteList")
camera.delete_plate("IB36NL", group="whiteList")
all_plates = camera.get_all_plates()  # every group, paged with resultOffset / maxResult / total

# Temporary visitor pass. Omitting begin_time and end_time lets the camera
# assign the validity window. Pass both when the pass should last N days.
from datetime import datetime, timedelta
start = datetime.now().replace(microsecond=0)
camera.add_plate(
    "IB36NL",
    group="temporary",
    owner="Visitor",
    card_number="1001",
    begin_time=start,
    end_time=start + timedelta(days=7),
)
this_week = camera.get_expiring_plates(days=7)

# Or use as context manager
with ViewtronCamera("192.168.0.20", "admin", "password") as cam:
    plates = cam.get_plates(group="whiteList")

Projects Using This SDK

Documentation

Products

Author

Mike Haldas — CCTV Camera Pros mike@cctvcamerapros.net

Metadata

Release files for viewtron 1.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for viewtron 1.4.1
File Size Uploaded
viewtron-1.4.1.tar.gz 42.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for viewtron 1.4.1
File Interpreter ABI Platform
viewtron-1.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 73.2 kB

Release files / viewtron-1.4.1.tar.gz

Download URL viewtron-1.4.1.tar.gz
Size 42.8 kB
Tags Source
SHA-256 checksum
How to use checksums
aeeaa31c71222feaa3d41b9c1d5333409de689750bae47ad33d736c2c889a87f
BLAKE2b-256 checksum
How to use checksums
b2903f846b7217ab96003840d3858c297273ddf76857419b132fec7055e0d6c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / viewtron-1.4.1-py3-none-any.whl

Download URL viewtron-1.4.1-py3-none-any.whl
Size 30.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6a69e8c56b701390e6d6d29424147dafc4c12ba668ed367eeda2f1eb866bfaca
BLAKE2b-256 checksum
How to use checksums
2ac174ae1f3f986c54c713c938464587a417db8abdbd2cc62c6d65967fdc1b13
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.4.1 This release

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page