Manually Add an ONVIF Device via C API

A comprehensive guide to configuring and connecting to an ONVIF device using the Happytimesoft Client Library.

Introduction

This tutorial demonstrates how to programmatically connect to a specific ONVIF device by manually setting its network address and credentials. This method is useful when automatic discovery is not feasible or you need direct control over the connection parameters. The code examples below are taken from the official onviftest2.cpp test program, which accepts the device address and credentials as command-line arguments:

Program Usage
// Usage: onviftest2 ip port https user pass
OnvifTest2 192.168.1.3 8000 0 admin admin

Step 1: Initialize the Library

Before defining the device, initialize the logging and internal buffers of the ONVIF client library, and start the event handler for receiving device notifications.

C Code: Initialization (from onviftest2)
// Define an ONVIF_DEVICE variable
ONVIF_DEVICE g_device;

// Open log file and set log level
log_init("onviftest2.log");
log_set_level(HT_LOG_DBG);

// Initialize system buffer
sys_buf_init(10 * MAX_DEV_NUMS);

// Initialize HTTP message buffer
http_msg_buf_init(10 * MAX_DEV_NUMS);

// Start the event handler (bind HTTP server to 0.0.0.0:30100)
onvif_event_init(1, NULL, 30100, 0, NULL, 0, NULL, NULL, 1, MAX_DEV_NUMS);

// Set event notify callback and subscribe-disconnect callback
onvif_set_event_notify_cb(eventNotifyCallback, 0);
onvif_set_subscribe_disconnect_cb(subscribeDisconnectCallback, 0);

// Initialize the device structure
memset(&g_device, 0, sizeof(g_device));

Step 2: Configure Device Address

Set the IP address, port, and HTTPS flag of the target device using onvif_initDevice. In the test program these values come from the command-line arguments.

C Code: Set Device Host and Port (from onvif_test2)
// Set device connection information
// onvif_initDevice(p_device, ip, port, https_flag)
onvif_initDevice(&g_device, argv[1], atoi(argv[2]), atoi(argv[3]));
// e.g. onvif_initDevice(&g_device, "192.168.1.3", 8000, 0);

Step 3: Set Authentication

Provide the username and password required to authenticate with the ONVIF device, choose the authentication method, and set a request timeout.

C Code: Set Credentials (from onvif_test2)
// Set device login information
onvif_SetAuthInfo(&g_device, argv[4], argv[5]);  // user, pass

// Set authentication method (UsernameToken recommended)
onvif_SetAuthMethod(&g_device, AuthMethod_UsernameToken);

// Set request timeout in milliseconds
onvif_SetReqTimeout(&g_device, 5000);

Step 4: Query Device Information

After configuration, call core ONVIF services to verify the connection and retrieve device information. If a call fails, invoke the error handler to diagnose the cause.

C Code: Test Connection & Get Info (from onvif_test2)
if (!GetSystemDateAndTime(&g_device))
{
    errorHandler(&g_device);
    printf("%s, GetSystemDateAndTime failed\r\n", g_device.binfo.XAddr.host);
}

if (!GetCapabilities(&g_device))
{
    errorHandler(&g_device);
    printf("%s, GetCapabilities failed\r\n", g_device.binfo.XAddr.host);
}

if (!GetServices(&g_device))
{
    errorHandler(&g_device);
    printf("%s, GetServices failed\r\n", g_device.binfo.XAddr.host);
}

if (!GetDeviceInformation(&g_device))
{
    errorHandler(&g_device);
    printf("%s, GetDeviceInformation failed\r\n", g_device.binfo.XAddr.host);
}

Step 5: Handle Errors

The errorHandler function checks two fields of the device structure: authFailed (authentication result) and errCode (error code). Use it after every failed call to understand what went wrong:

C Code: Error Handler (from onvif_test2)
void errorHandler(ONVIF_DEVICE * p_device)
{
    if (p_device->authFailed) // Authentication failed
    {
        printf("Authentication failed\r\n");
    }

    switch (p_device->errCode)
    {
    case ONVIF_ERR_ConnFailure:          // Connection failed
        printf("connect failure\r\n"); break;
    case ONVIF_ERR_MallocFailure:         // Failed to allocate memory
        printf("memory malloc failure\r\n"); break;
    case ONVIF_ERR_NotSupportHttps:       // Device requires HTTPS, library lacks HTTPS
        printf("not support https\r\n"); break;
    case ONVIF_ERR_RecvTimeout:           // Message receiving timeout
        printf("message receive timeout\r\n"); break;
    case ONVIF_ERR_InvalidContentType:    // Invalid content type in response
        printf("invalid content type\r\n"); break;
    case ONVIF_ERR_NullContent:           // No content in response
        printf("null content\r\n"); break;
    case ONVIF_ERR_ParseFailed:           // Failed to parse the message
        printf("message parse failed\r\n"); break;
    case ONVIF_ERR_HandleFailed:          // Message handling failed
        printf("message handle failed\r\n"); break;
    case ONVIF_ERR_HttpResponseError:     // Device responded with an error
        printf("code=%s\r\n", p_device->fault.Code);
        printf("subcode=%s\r\n", p_device->fault.Subcode);
        printf("reason=%s\r\n", p_device->fault.Reason);
        break;
    default:
        break;
    }
}

Step 6: Subscribe to Events (Optional)

If the device supports the ONVIF event service (Capabilities.events.support == 1), subscribe to its event notifications. The client automatically receives events through the callback registered in Step 1, and re-subscribes if the subscription disconnects.

C Code: Subscribe to Events (from onvif_test2)
if (g_device.Capabilities.events.support == 1)
{
    if (Subscribe(&g_device, getDeviceIndex(&g_device)))
    {
        printf("Subscribe successful!\r\n");
    }
    else
    {
        errorHandler(&g_device);
        printf("Subscribe failed!\r\n");
    }
}

// The event notify callback receives topics:
void eventNotifyCallback(Notify_REQ * p_req, void * p_data)
{
    NotificationMessageList * p_notify = p_req->notify;
    while (p_notify)
    {
        printf("\tTopic : %s\r\n", p_notify->NotificationMessage.Topic);
        p_notify = p_notify->next;
    }
}

Step 7: Clean Up

Before the application exits, release the device resources and de-initialize the library buffers:

C Code: Cleanup (from onvif_test2)
onvif_free_device(&g_device);   // free device resources
onvif_event_deinit();             // stop the event handler
http_msg_buf_deinit();            // free HTTP message buffer
sys_buf_deinit();                 // free system buffer
log_close();                      // close the log file

Key Configuration Points

  • IP Address: Replace 192.168.1.3 with your device's actual IP.
  • Port: Common ports are 80, 8000, 8899. Check your camera's documentation.
  • HTTPS flag: Set to 1 in onvif_initDevice when connecting over HTTPS. If the device requires HTTPS but the library was built without HTTPS support, ONVIF_ERR_NotSupportHttps is returned.
  • Credentials: Use the correct username and password for your device; check authFailed after failed calls.
  • Error diagnosis: Always call errorHandler (or inspect errCode / fault) after a failed API call to identify the root cause.
  • Event init required for subscriptions: Call onvif_event_init and register the notify callback before subscribing to device events.