
I recently bought a Dahua H5A 5MP 360° Indoor Wi-Fi 6 (DH-H5A / IPC-H5A) pan-tilt camera and placed it on my isolated camera VLAN (172.16.60.0/24) with internet access blocked at the firewall. My only goal was simple: add my own camera to Home Assistant so I could toggle the physical privacy shutter, AI human/pet detection, status LED, and PTZ locally. Five minutes after plugging it in, I hit a wall—opening http://172.16.60.46/ returned 404 Page Not Found, and none of the standard Dahua /cgi-bin/*.cgi endpoints worked.
I am not a reverse engineer and I have zero interest in reading assembly by hand—I didn’t even know how half of these binary protocols worked under the hood, I just wanted the camera I bought to work in Home Assistant. So I downloaded the official Dahua apps (macOS, Windows, and Android) into a local folder, handed the directory and the camera IP to Google Antigravity running Gemini 4 Argon High, and asked the agent to figure out how the camera communicates and build an open-source Home Assistant integration for me. Within a single session, Antigravity autonomously unpacked the installers, analyzed the binary protocol on TCP Port 37777, and generated open-dahua-h5a—a clean-room Python library, CLI (dahua-h5a), and multi-camera HACS integration (custom_components/dahua_h5a).
Legal & Interoperability Disclaimer (EU Directive 2009/24/EC & § 69e UrhG):
This project and article were created exclusively for interoperability purposes—specifically to allow legal owners of Dahua H5A / Hero-series hardware to integrate their own devices with open-source smart home software (Home Assistant) over a local network.
Under Article 6 of the EU Software Directive (2009/24/EC) and § 69e of the German Copyright Act (Urheberrechtsgesetz — Dekompilierung), observing, studying, and decompiling software to obtain the information necessary to achieve interoperability of an independently created program is explicitly permitted by law when that protocol information is not publicly documented by the manufacturer.
- No security bypass or hacking: This integration does not bypass authentication, encryption, or access controls. You must know and provide your own valid
adminpassword to communicate with the camera.- 100% Clean-Room Open Source: The
open-dahua-h5arepository contains zero vendor code, proprietary SDK libraries, binary blobs, or firmware files—only an independent Pythonasyncioclient written from scratch.- No affiliation: This project is an independent community interoperability effort and is not affiliated with, endorsed by, or supported by Dahua Technology.
1. Why Existing Dahua Integrations Fail on the H5A

Standard commercial Dahua IPCs expose an HTTP CGI API (/cgi-bin/magicBox.cgi, /cgi-bin/configManager.cgi) on port 80. Consumer Hero-series cameras like the Dahua H5A (FW V2.860.0000000.26.R) disable the embedded web UI and CGI endpoints completely. When Antigravity queried magicBox.getProductDefinition on the camera, the firmware reported:
|
|
Scanning the camera on the local VLAN showed only three open TCP ports:
- TCP
80(gSOAP/2.8): Runs a minimal ONVIF service (/onvif/device_service,/onvif/media_service,/onvif/ptz_service). - TCP
554(RTSP): Streams 5MP H.265 video (subtype=0) and SD substream (subtype=1). - TCP
37777(Dahua NetSDK / DVR2): The binary control channel used by DahuaConfigTooland theDMSSmobile app.
Note / Gotcha: During testing, Antigravity discovered a nasty trap with ONVIF on port
80. The H5A keeps a separateONVIFuser table wherePasswordChangeFlagdefaults tofalseeven after you initialize the camera’sadminpassword. Every failed WS-UsernameToken request against/onvif/media_servicedecrements a hardware lockout counter (You still have 28 attempt(s)). Because of that, the integration avoids ONVIF completely and uses TCP37777for control and RTSP554for video and snapshots.
2. Letting Google Antigravity Analyze the Vendor Protocol
Instead of spending weeks learning binary protocol analysis myself, I dropped the vendor installers into /home/wojcieh/DevProjects/dahua/ and told Google Antigravity: “Here is the camera IP and password, and here are the Windows, macOS, and Android apps—plan the analysis so we can build an open-source client and control every feature in Home Assistant.”
Antigravity set up an isolated workspace and inspected the official client packages purely to understand the wire format needed for interoperability:
- macOS
ConfigTool.app: Inspected the shared libraries (libdhnetsdk.so,libdhconfigsdk.so) to see how desktop clients frame TCP37777packets. - Android
DMSS 2.6.22: Checked the mobile configuration tables (libnetsdk.so,libconfigsdk.so) for consumer-only IoT features like the privacy lens mask and baby cry detection. - Windows
ConfigTool V5.001: Cross-checked the configuration schema definitions (dhconfigsdk.dll).
To be completely transparent: I barely understand the low-level assembly or byte offsets that Antigravity extracted below—my role was defining the goal and verifying that the physical camera in my bedroom actually moved and closed its shutter when I ran the resulting commands.
| Protocol Handler in Client SDK | Wire Function |
|---|---|
CDevLogin::PacketStep1_dvr2 |
Builds the 32-byte 0xa0 login challenge request |
CDevLogin::ParseStep1Rsp_dvr2 |
Parses Encryption (Default), Random, and Realm |
DH_Superencipherment |
Iterative MD5 -> Base62 password hash (Default mode) |
CDevLogin::PacketStep2_dvr2 |
Sends the authenticated "{user}&&{H1}{H2}" credential frame |
sendJsonPacket_dvr2 |
Wraps JSON-RPC 2.0 payloads inside 32-byte 0xf6 headers |
Parse_f6 |
Reassembles multi-chunk 0xf6 JSON-RPC responses and events |
3. How the Port 37777 Interoperability Protocol Works
Based on Antigravity’s protocol spec (docs/PROTOCOL_SPEC.md), every frame on TCP port 37777 starts with a 32-byte little-endian header (hdr[0] = packet command, hdr[4:8] = uint32_le(payload_len)).
Two-Step 0xa0 Challenge-Response Authentication
When connecting to 172.16.60.46:37777, the client sends a 32-byte 0xa0 challenge request with trailer bytes 01 02 00 01 3c 00 a1 aa at hdr[24:32]. The camera replies with a 0xb0 challenge containing its Realm and a one-time Random nonce:
|
|
In Step 2, the client hashes the user’s password using two MD5 digests (H1 for the Realm and H2 using a Base62 DH_Superencipherment transformation combined with the Random nonce) and sends "{user}&&{H1}{H2}". When the password is valid, the camera returns hdr[8] == 0x00 and assigns a 32-bit session_id at hdr[16:20].
Embedded 0xf6 JSON-RPC Framing
Once logged in, all configuration and PTZ commands travel over the same TCP socket as 0xf6 packets:
|
|
Querying configManager.getMemberNames and <component>.listMethod on the camera exposed 126 configuration tables and 316 RPC methods, which Antigravity mapped into clean Python methods:
AELensMask: Physical privacy shutter (Status: truehides the lens inside the housing;falseopens it).SmartMotionDetect: On-device AI human detection (ObjectTypes.Human), pet detection (ObjectTypes.Animal), and PTZ auto-tracking (SmartTrack).AudioDetect: Baby cry and abnormal sound detection (Enable,AnomalyDetect,AnomalySensitive).LightGlobal: Front status LED toggle (Enable).Lighting+VideoInDayNight: IR illuminator mode (Auto/Manual/Off) and ICR filter (Brightness/Color/BlackWhite).ptz.factory.instance: Controlsptz.start,ptz.stop,ptz.gotoPreset,ptz.setPreset, andptz.restartPtz.eventManager.attach: Subscribes the TCP socket to real-timeclient.notifyEventStreampush events (VideoMotion,SmartMotionHuman,SmartMotionAnimal,AudioMutation).
4. Using the odh CLI and Python Library
The resulting open-source project open-dahua-h5a (available on GitHub and Codeberg) uses only Python’s standard asyncio library—no vendor SDKs or compiled binaries required. The CLI is available as odh (Open Dahua) or dahua-h5a.
- Clone the repository and install it in a virtual environment:
|
|
- Run
odhcommands against your camera:
|
|
5. Multi-Camera Home Assistant Integration via HACS
What I really cared about was having a plug-and-play Home Assistant integration where you simply enter the camera’s IP address and password in the UI—and can add as many cameras as you want without touching YAML. Antigravity packaged a complete Home Assistant Custom Integration (custom_components/dahua_h5a) with ConfigFlow, ReconfigureFlow, and OptionsFlow.

Installing via HACS
- Open HACS in Home Assistant, click the three-dot menu in the top right corner, and select Custom repositories.
- Paste
https://github.com/wojciehm/open-dahua-h5aand choose Integration as the category. - Click Download and restart Home Assistant.
- Go to Settings -> Devices & Services -> Add Integration and search for Dahua H5A (Local NetSDK).
- Enter the camera’s IP / Hostname (e.g.,
172.16.60.46), NetSDK Port (37777), RTSP Port (554), Username (admin), and Password.
If you have multiple H5A or Hero-series cameras across different rooms, click Add Integration for each one. During setup, config_flow.py logs in over TCP 37777, fetches the hardware serial number via magicBox.getSerialNo as the unique_id, and names the device after its configured MachineName (for example, Sypialnia or Kuchnia).

Each camera exposes 31 native entities out of the box (with English and Polish translations):
camera(1): 5MP H.265 Live Stream (subtype=0) or Sub Stream (subtype=1), RTSP snapshots,turn_on/turn_offtied to the physical privacy shutter, and entity services (dahua_h5a.ptz_move,dahua_h5a.ptz_goto_preset,dahua_h5a.ptz_set_preset,dahua_h5a.trigger_siren).switch(10): Privacy Mask, AI Human Detection, AI Pet Detection, Smart Auto-Tracking, Motion Detection, Abnormal Sound / Baby Cry Detection, Status LED, Stream Audio Recording, Image Mirror, and 180° Image Flip.select(2): Night Vision IR Mode (auto/off/on) and dynamic PTZ Preset selector.number(3): Speaker Volume (0–100%), Microphone Sensitivity (0–100%), and Sound Detection Sensitivity (1–100%).button(6): PTZ Tilt Up, Tilt Down, Pan Left, Pan Right, Calibrate PTZ, and Trigger Siren.binary_sensor(4): Real-time push sensors (local_push) for Motion, Person Detected, Sound / Cry Detected, and Privacy Shutter Closed.sensor(5): MicroSD Card Status, MicroSD Used (%), MicroSD Free Space (GB), PTZ Pan Angle, and PTZ Tilt Angle.
Summary
For me, this was the ultimate test of agentic engineering with Google Antigravity: I started with an offline camera that had no web UI and no documented HTTP API, gave the agent the vendor apps and my goal, and ended up with a clean-room Python library and a multi-camera HACS plugin that controls every hardware feature locally. All code and interoperability documentation are available in open-dahua-h5a under the MIT license.