Skip to main content

Table of Contents

viewtron.server

Viewtron HTTP Server — receives alarm events from Viewtron IP cameras and NVRs.

Handles all the connection details that Viewtron cameras require: HTTP/1.1 persistent connections, keepalive responses, XML success replies, and multi-threaded request handling.

Usage: from viewtron import ViewtronServer

def on_event(event, client_ip): print(f"[{event.category}] {event.get_alarm_type()} from {client_ip}") if event.category == "lpr": print(f" Plate: {event.get_plate_number()}") print(f" Group: {event.get_plate_group()}")

def on_unparsed(xml, client_ip, reason): print(reason, client_ip)

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

You can find Viewtron IP cameras at https://www.cctvcamerapros.com/viewtron-security-cameras-s/1476.htm

ViewtronServer Objects​

class ViewtronServer()

HTTP server that receives events from Viewtron IP cameras.

Arguments:

  • port - Port to listen on (default 5050)

  • on_event - Callback function(event, client_ip) called for each parsed alarm event. event is a ViewtronEvent instance with .category, .get_alarm_type(), .get_plate_number(), etc.

  • on_connect - Optional callback(client_ip) called when a camera first connects (sends its first keepalive).

  • on_raw - Optional callback(xml_text, client_ip) called with the raw XML body of every POST (before parsing). Useful for logging or debugging. Traject posts are not passed here.

  • on_unparsed - Optional callback(xml_text, client_ip, reason) called when a POST body is not a keepalive and does not become an event. reason is one of:

    • "unknown-smartType" — smartType is not in the table for that envelope (for example MOTION, or VEHICLE in a version-2 post that has no licensePlateListInfo)
    • "no-messageType" — a version-2 post has no messageType and is not an IPC-style body
    • "parse-error" — the body is not well-formed XML
    • "alarmStatus" — an alarm on/off status post

    Chunked request bodies (Transfer-Encoding: chunked) are decoded. A chunked POST is never treated as the empty-body keepalive, even when Content-Length is missing or 0.

Example:

from viewtron import ViewtronServer

def on_event(event, client_ip): if event.category == "lpr": plate = event.get_plate_number() group = event.get_plate_group() print(f"Plate {plate} - Group: {group}")

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

serve_forever​

def serve_forever()

Start the server and block until interrupted.

shutdown​

def shutdown()

Stop the server from another thread.