Qt audio and video development 34 onvif time setting

1, Foreword

It is necessary to set the time of the device. This is a necessary function. After all, most front-end devices, such as the camera itself, do not have BIOS battery, so it is impossible to store the time. Either set the NTP address to synchronize the time, or other devices take the initiative to set the time. If the time is incorrect, it means that the time string displayed on the local screen and the locally stored video files may be incorrect, Therefore, the general processing is to set the time of the camera to the time of the NVR immediately after the NVR is connected to the camera equipment, so as to maintain consistency.

There are two main ways to set the time with onvif: one is to actively call NTP synchronization after setting the NTP service address, and the other is to send the date and time data packet to the device for its own analysis and processing. It should be noted here that the date and time in the data packet is in UTC format, that is, London time, so it needs to be converted locally into UTC time before sending, Qt has built-in method for converting to UTC time qdatetime:: currentdatetime() toUTC().

Main functions of onvif:

  1. Search for equipment and obtain equipment information, such as manufacturer, model, etc.
  2. Get multiple configuration file information of the device.
  3. Obtain the video stream address rtsp, resolution and other parameters of the corresponding configuration file.
  4. Pan tilt control, moving up, down, left and right, zoom in and out, relative and absolute movement.
  5. Obtain the preset bit information and trigger the preset bit.
  6. Subscribe to events and receive various messages of the device, especially alarm events, such as the alarm of IO port.
  7. Capture the current picture of the device.
  8. Obtain, create and delete user information.
  9. Obtain device and network configuration information, such as IP address.
  10. Get and set NTP time synchronization and set device time.
  11. Get and set video parameters and picture parameters (brightness, color, saturation).
  12. Restart the device.

Processing flow of onvif:

  1. Bind multicast IP ( and port (3702) to send data search equipment in fixed xml format.
  2. Analyze the received data in xml format to get the Onvif address of the device.
  3. Send the corresponding data to the Onvif address, and take out the corresponding node data after receiving the data.
  4. Request the Onvif address to obtain the Media address and Ptz address. The Media address is used to obtain the detailed configuration file, and the Ptz address is used for Ptz control.
  5. PTZ control is to send corresponding data to PTZ address.
  6. If user authentication is set, the user token information needs to be sent together, and authentication processing needs to be performed every time.
  7. The received data is not standard xml data and cannot be processed according to normal node parsing. It can only be done with QXmlQuery.
  8. The data returned by the equipment of each manufacturer may not be completely consistent, but they are basically inconsistent. It is necessary to fuzzy search the node value.
  9. The underlying protocol resolution is specially adopted, because soap is too bulky, the function name is too alternative, and it is deliberately lightweight.
  10. Two necessary tools, Onvif Device Manager and Onvif Device Test Tool.

2, Functional features

  1. The broadcast search device supports IPC and NVR, returns in turn, and can select different network card IP.
  2. Obtain Onvif address, Media address, Profile file and Rtsp address in turn.
  3. The Rtsp address of video stream can be obtained for the specified Profile, such as the address of main code stream and sub code stream.
  4. Onvif can be used to obtain the detailed information of each user authentication.
  5. The camera image can be previewed in real time.
  6. Support PTZ control, adjust PTZ up, down, left and right, support absolute movement and relative movement, and put and reduce the distance of the image.
  7. Support any QT version of Qt4 and Qt5, and test Qt4 7.0 to Qt5 14.2.
  8. Support any compiler and test mingw, msvc, gcc and clang.
  9. Support any operating system, test xp, win7, win10, android, linux, embedded linux, raspberry faction H3, etc.
  10. It supports any Onvif camera and NVR, personally tests the chip cores of Haikang, Dahua, Yushi, Huawei and Hisilicon, and can be customized and developed.
  11. Unicast search for specified IP address and onvif address is supported. For example, it is very useful in the case of cross network segment.
  12. It supports filtering search devices by specifying filter criteria.
  13. Support the setting of search interval to ensure that all devices are searched back, which is very useful in a large number of device sites.
  14. Picture parameters (brightness, color degree, saturation) can be set.
  15. Support NTP timing and time synchronization settings.
  16. Written in pure Qt, it is super compact and lightweight, with a total of about 2000 lines of code. It does not rely on any third-party libraries and components, and is cross platform.
  17. Encapsulated the general data sending and receiving analysis functions, it is very convenient to expand other Onvif processing.
  18. The tool provides a send / receive data text box to display the send / receive data, which is convenient for viewing and analysis.
  19. It supports all Onvif devices with neat code and friendly interface. It can be used directly by introducing pri.

3, Renderings

4, Related sites

  1. Domestic sites: https://gitee.com/feiyangqingyun/QWidgetDemo
  2. International sites: https://github.com/feiyangqingyun/QWidgetDemo
  3. Personal homepage: https://blog.csdn.net/feiyangqingyun
  4. Zhihu homepage: https://www.zhihu.com/people/feiyangqingyun/
  5. Experience address: https://blog.csdn.net/feiyangqingyun/article/details/97565652

5, Core code

QString OnvifOther::getDateTime()
    QString result = writeData("GetSystemDateAndTime", "tt:Year|tt:Month|tt:Day|tt:Hour|tt:Minute|tt:Second|tt:TZ", "Get time", true, true);
    QStringList list = result.split(ResultSplit);
    if (list.count() != 7) {
        return result;

    QString year = list.at(0).split(":").last();
    QString month = list.at(1).split(":").last();
    QString day = list.at(2).split(":").last();
    QString hour = list.at(3).split(":").last();
    QString min = list.at(4).split(":").last();
    QString sec = list.at(5).split(":").last();

    //Calculate time zone and assign value
    QString timezone = list.at(6);
    timezone = timezone.mid(6, timezone.length() - 6);
    device->timezone = timezone;

    //Calculate the date according to the time zone
    QString str = QString("%1-%2-%3 %4:%5:%6").arg(year).arg(month).arg(day).arg(hour).arg(min).arg(sec);
    QDateTime dt = QDateTime::fromString(str, "yyyy-M-d h:m:s");
    if (!device->timezone.contains("GMT-08")) {
        dt = dt.addSecs(8 * 60 * 60);

    //Zero filling for less than two digits
    list = dt.toString("yyyy-M-d-h-m-s").split("-");
    result = QString("%1-%2-%3 %4:%5:%6 %7").arg(list.at(0)).arg(list.at(1), 2, '0').arg(list.at(2), 2, '0')
             .arg(list.at(3), 2, '0').arg(list.at(4), 2, '0').arg(list.at(5), 2, '0').arg(timezone);
    return result;

bool OnvifOther::setDateTime(const QDateTime &datetime, bool ntp)
    QStringList temp = datetime.toString("yyyy-M-d-h-m-s").split("-");
    QString wsdl = "http://www.onvif.org/ver10/device/wsdl";
    QString schema = "http://www.onvif.org/ver10/schema";

    QStringList list;
    list << QString("    <SetSystemDateAndTime xmlns=\"%1\">").arg(wsdl);
    list << QString("      <DateTimeType>%1</DateTimeType>").arg(ntp ? "NTP" : "Manual");
    list << QString("      <DaylightSavings>%1</DaylightSavings>").arg("false");
    list << QString("      <TimeZone>");
    list << QString("        <TZ xmlns=\"%1\">%2</TZ>").arg(schema).arg(ntp ? device->timezone : "CST-8");
    list << QString("      </TimeZone>");

    if (!ntp) {
        list << QString("      <UTCDateTime>");
        list << QString("        <Date xmlns=\"%1\">").arg(schema);
        list << QString("          <Year>%1</Year>").arg(temp.at(0));
        list << QString("          <Month>%1</Month>").arg(temp.at(1));
        list << QString("          <Day>%1</Day>").arg(temp.at(2));
        list << QString("        </Date>");
        list << QString("        <Time xmlns=\"%1\">").arg(schema);
        list << QString("          <Hour>%1</Hour>").arg(temp.at(3));
        list << QString("          <Minute>%1</Minute>").arg(temp.at(4));
        list << QString("          <Second>%1</Second>").arg(temp.at(5));
        list << QString("        </Time>");
        list << QString("      </UTCDateTime>");

    list << QString("    </SetSystemDateAndTime>");

    QString result = writeData(list.join("\r\n"), "SetSystemDateAndTimeResponse", "Set time", false);
    return result.contains("SetSystemDateAndTimeResponse");

QString OnvifOther::writeData(const QString &key, const QString &value, const QString &flag,
                              bool xmlns, bool value4, quint8 type)
    if (device->deviceUrl.isEmpty()) {
        return QString();

    QString file = device->request->getSendData(key, true, xmlns);
    QByteArray dataSend = file.toUtf8();
    //The last parameter indicates that the timeout time is usually very fast. Unless the other party is not online, the card needs to set the timeout time for a long time
    QNetworkReply *reply = device->request->post(device->deviceUrl, dataSend, 3000);
    emit sendData(dataSend, device->deviceUrl);

    QStringList results;
    QByteArray dataReceive;
    bool ok = device->checkData(reply, dataReceive, flag);
    if (ok) {
        OnvifQuery query;

        if (type == 0) {
            if (!value.isEmpty()) {
                //There may be multiple keywords to obtain
                QStringList list = value.split("|");
                foreach (QString str, list) {
                    QString result = value4 ? query.getValue4(str) : query.getValue3(str);
                    if (result != "-1") {
                        results << QString("%1:%2").arg(str).arg(result);
        } else if (type == 1) {
            results = query.getVideoSource();

    return results.join(ResultSplit);

Tags: Qt

Posted by priya_cks on Wed, 11 May 2022 18:57:40 +0300