add code
This commit is contained in:
commit
80b1e1f940
|
@ -0,0 +1 @@
|
||||||
|
vendor/
|
|
@ -0,0 +1,402 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--W3C XML Schema generated by XMLSpy v2017 (x64) (http://www.altova.com)-->
|
||||||
|
<!--
|
||||||
|
Copyright (c) 2008-2023 by ONVIF: Open Network Video Interface Forum. All rights reserved.
|
||||||
|
|
||||||
|
Recipients of this document may copy, distribute, publish, or display this document so long as this copyright notice, license and disclaimer are retained with all copies of the document. No license is granted to modify this document.
|
||||||
|
|
||||||
|
THIS DOCUMENT IS PROVIDED "AS IS," AND THE CORPORATION AND ITS MEMBERS AND THEIR AFFILIATES, MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THIS DOCUMENT ARE SUITABLE FOR ANY PURPOSE; OR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
|
||||||
|
IN NO EVENT WILL THE CORPORATION OR ITS MEMBERS OR THEIR AFFILIATES BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THIS DOCUMENT, WHETHER OR NOT (1) THE CORPORATION, MEMBERS OR THEIR AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR (2) SUCH DAMAGES WERE REASONABLY FORESEEABLE, AND ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THIS DOCUMENT. THE FOREGOING DISCLAIMER AND LIMITATION ON LIABILITY DO NOT APPLY TO, INVALIDATE, OR LIMIT REPRESENTATIONS AND WARRANTIES MADE BY THE MEMBERS AND THEIR RESPECTIVE AFFILIATES TO THE CORPORATION AND OTHER MEMBERS IN CERTAIN WRITTEN POLICIES OF THE CORPORATION.
|
||||||
|
-->
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" targetNamespace="http://www.onvif.org/ver10/schema" elementFormDefault="qualified" version="23.06">
|
||||||
|
<!--===============================-->
|
||||||
|
<!-- Generic Types -->
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:simpleType name="ReferenceToken">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Unique identifier for a physical or logical resource.
|
||||||
|
Tokens should be assigned such that they are unique within a device. Tokens must be at least unique within its class.
|
||||||
|
Length up to 64 characters. Token may be extended by intermediate terminal with adding prefix to make it global unique.
|
||||||
|
The length should be within 36 characters for generating at local device. See "Remote Token" section in Resource Query specification.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:maxLength value="64"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="IntRange">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Range of values greater equal Min value and less equal Max value.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Min" type="xs:int"/>
|
||||||
|
<xs:element name="Max" type="xs:int"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<!-- Start PTZ Related Types -->
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="Vector2D">
|
||||||
|
<xs:attribute name="x" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="y" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="space" type="xs:anyURI" use="optional">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Pan/tilt coordinate space selector. The following options are defined:<ul>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace</li>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/PanTiltSpaces/TranslationGenericSpace</li>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace</li>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace</li>
|
||||||
|
</ul>
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="Vector1D">
|
||||||
|
<xs:attribute name="x" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="space" type="xs:anyURI" use="optional">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Zoom coordinate space selector. The following options are defined:<ul style="">
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace</li>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/ZoomSpaces/TranslationGenericSpace</li>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/ZoomSpaces/VelocityGenericSpace</li>
|
||||||
|
<li> http://www.onvif.org/ver10/tptz/ZoomSpaces/ZoomGenericSpeedSpace</li>
|
||||||
|
</ul>
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="PTZVector">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="PanTilt" type="tt:Vector2D" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Pan and tilt position. The x component corresponds to pan and the y component to tilt.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Zoom" type="tt:Vector1D" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
A zoom position.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="PTZStatus">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Position" type="tt:PTZVector" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Specifies the absolute position of the PTZ unit together with the Space references. The default absolute spaces of the corresponding PTZ configuration MUST be referenced within the Position element.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="MoveStatus" type="tt:PTZMoveStatus" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Indicates if the Pan/Tilt/Zoom device unit is currently moving, idle or in an unknown state.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Error" type="xs:string" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
States a current PTZ error.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="UtcTime" type="xs:dateTime">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Specifies the UTC time when this status was generated.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first Vendor then ONVIF -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:anyAttribute processContents="lax"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="PTZMoveStatus">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="PanTilt" type="tt:MoveStatus" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Zoom" type="tt:MoveStatus" minOccurs="0">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:simpleType name="MoveStatus">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="IDLE"/>
|
||||||
|
<xs:enumeration value="MOVING"/>
|
||||||
|
<xs:enumeration value="UNKNOWN"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<!--===============================-->
|
||||||
|
<!-- Event and Analytics Types -->
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="Vector">
|
||||||
|
<xs:attribute name="x" type="xs:float"/>
|
||||||
|
<xs:attribute name="y" type="xs:float"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="Rectangle">
|
||||||
|
<xs:attribute name="bottom" type="xs:float"/>
|
||||||
|
<xs:attribute name="top" type="xs:float"/>
|
||||||
|
<xs:attribute name="right" type="xs:float"/>
|
||||||
|
<xs:attribute name="left" type="xs:float"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="Polygon">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Point" type="tt:Vector" minOccurs="3" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:element name="Polygon" type="tt:Polygon"/>
|
||||||
|
<xs:complexType name="Color">
|
||||||
|
<xs:attribute name="X" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="Y" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="Z" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="Colorspace" type="xs:anyURI">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Acceptable values:
|
||||||
|
<ul>
|
||||||
|
<li>http://www.onvif.org/ver10/colorspace/YCbCr - YCbCr
|
||||||
|
<ul><li>X attribute = Y value</li>
|
||||||
|
<li>Y attribute = Cb value</li>
|
||||||
|
<li>Z attribute = Cr value</li></ul>
|
||||||
|
</li>
|
||||||
|
<li>http://www.onvif.org/ver10/colorspace/RGB - RGB
|
||||||
|
<ul><li>X attribute = R value</li>
|
||||||
|
<li>Y attribute = G value</li>
|
||||||
|
<li>Z attribute = B value</li></ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
If the Colorspace attribute is absent and not defined on higher level, YCbCr is implied.
|
||||||
|
|
||||||
|
Deprecated values:
|
||||||
|
<ul>
|
||||||
|
<li>http://www.onvif.org/ver10/colorspace/CIELUV - CIE LUV</li>
|
||||||
|
<li>http://www.onvif.org/ver10/colorspace/CIELAB - CIE 1976 (L*a*b*)</li>
|
||||||
|
<li>http://www.onvif.org/ver10/colorspace/HSV - HSV</li>
|
||||||
|
</ul>
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="Likelihood" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Likelihood that the color is correct.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:anyAttribute processContents="lax"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="ColorCovariance">
|
||||||
|
<xs:attribute name="XX" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="YY" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="ZZ" type="xs:float" use="required"/>
|
||||||
|
<xs:attribute name="XY" type="xs:float"/>
|
||||||
|
<xs:attribute name="XZ" type="xs:float"/>
|
||||||
|
<xs:attribute name="YZ" type="xs:float"/>
|
||||||
|
<xs:attribute name="Colorspace" type="xs:anyURI">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
Acceptable values are the same as in tt:Color.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:anyAttribute processContents="lax"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="ColorDescriptor">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="ColorCluster" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Color" type="tt:Color"/>
|
||||||
|
<xs:element name="Weight" type="xs:float" minOccurs="0"/>
|
||||||
|
<xs:element name="Covariance" type="tt:ColorCovariance" minOccurs="0"/>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- reserved for ONVIF -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:anyAttribute processContents="lax"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Extension" type="xs:anyType" minOccurs="0"/>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- reserved for ONVIF -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:anyAttribute processContents="lax"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<!-- Scene Description Types -->
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="Transformation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Translate" type="tt:Vector" minOccurs="0"/>
|
||||||
|
<xs:element name="Scale" type="tt:Vector" minOccurs="0"/>
|
||||||
|
<xs:element name="Extension" type="tt:TransformationExtension" minOccurs="0"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:anyAttribute processContents="lax"/>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="TransformationExtension">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first Vendor then ONVIF -->
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<!-- Location/Orientation Types -->
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="GeoLocation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first ONVIF then Vendor -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="lon" type="xs:double">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>East west location as angle.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="lat" type="xs:double">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>North south location as angle.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="elevation" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Hight in meters above sea level.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:anyAttribute/>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="GeoOrientation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first ONVIF then Vendor -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="roll" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Rotation around the x axis.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="pitch" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Rotation around the y axis.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="yaw" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Rotation around the z axis.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:anyAttribute/>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="LocalLocation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first ONVIF then Vendor -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="x" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>East west location as angle.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="y" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>North south location as angle.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="z" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Offset in meters from the sea level.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:anyAttribute/>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="LocalOrientation">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first ONVIF then Vendor -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="pan" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Rotation around the y axis.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="tilt" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Rotation around the z axis.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="roll" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Rotation around the x axis.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:anyAttribute/>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="SphericalCoordinate">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> <!-- first ONVIF then Vendor -->
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="Distance" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Distance in meters to the object.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="ElevationAngle" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Elevation angle in the range -90 to 90 degrees, where 0 is in level with the x-y plane.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="AzimuthAngle" type="xs:float">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Azimuth angle in the range -180 to 180 degrees counter clockwise, where 0 is rightwards.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:simpleType name="Entity">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="Device"/>
|
||||||
|
<xs:enumeration value="VideoSource"/>
|
||||||
|
<xs:enumeration value="AudioSource"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
<!--===============================-->
|
||||||
|
<xs:complexType name="LocationEntity">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="GeoLocation" type="tt:GeoLocation" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Location on earth.</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="GeoOrientation" type="tt:GeoOrientation" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Orientation relative to earth.</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="LocalLocation" type="tt:LocalLocation" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Indoor location offset.</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="LocalOrientation" type="tt:LocalOrientation" minOccurs="0">
|
||||||
|
<xs:annotation><xs:documentation>Indoor orientation offset.</xs:documentation></xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="Entity" type="xs:string">
|
||||||
|
<xs:annotation><xs:documentation>Entity type the entry refers to, use a value from the tt:Entity enumeration.</xs:documentation></xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="Token" type="tt:ReferenceToken">
|
||||||
|
<xs:annotation><xs:documentation>Optional entity token.</xs:documentation></xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="Fixed" type="xs:boolean">
|
||||||
|
<xs:annotation><xs:documentation>If this value is true the entity cannot be deleted.</xs:documentation></xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="GeoSource" type="xs:anyURI">
|
||||||
|
<xs:annotation><xs:documentation>Optional reference to the XAddr of another devices DeviceManagement service.</xs:documentation></xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="AutoGeo" type="xs:boolean">
|
||||||
|
<xs:annotation><xs:documentation>If set the geo location is obtained internally.</xs:documentation></xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
<!--===============================-->
|
||||||
|
</xs:schema>
|
|
@ -0,0 +1,153 @@
|
||||||
|
package goonvif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
search_sdk "git.pyer.club/kingecg/goonvif/sdk/search"
|
||||||
|
"git.pyer.club/kingecg/goonvif/search"
|
||||||
|
"github.com/beevik/etree"
|
||||||
|
"github.com/use-go/onvif"
|
||||||
|
device "github.com/use-go/onvif/device"
|
||||||
|
sdk "github.com/use-go/onvif/sdk/device"
|
||||||
|
wsdiscovery "github.com/use-go/onvif/ws-discovery"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
onvif.DeviceParams
|
||||||
|
device *onvif.Device
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrAuthRequired = errors.New("auth required")
|
||||||
|
|
||||||
|
func NewDevice(params onvif.DeviceParams) *Device {
|
||||||
|
return &Device{DeviceParams: params, ctx: context.Background()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) check() error {
|
||||||
|
if d.device != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if d.Username == "" || d.Password == "" {
|
||||||
|
return ErrAuthRequired
|
||||||
|
}
|
||||||
|
if d.HttpClient == nil {
|
||||||
|
d.HttpClient = new(http.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
device, err := onvif.NewDevice(d.DeviceParams)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.device = device
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (d *Device) GetCapabilities() (interface{}, error) {
|
||||||
|
err := d.check()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cap := device.GetCapabilities{Category: "All"}
|
||||||
|
|
||||||
|
getCapabilitiesResponse, err := sdk.Call_GetCapabilities(d.ctx, d.device, cap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r := getCapabilitiesResponse.Capabilities
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) GetRecordingSummary() (search.RecordingSummary, error) {
|
||||||
|
err := d.check()
|
||||||
|
if err != nil {
|
||||||
|
return search.RecordingSummary{}, err
|
||||||
|
}
|
||||||
|
resp, rerr := search_sdk.Call_GetRecordingSummary(d.ctx, d.device, search.GetRecordingSummary{})
|
||||||
|
if rerr != nil {
|
||||||
|
return search.RecordingSummary{}, rerr
|
||||||
|
}
|
||||||
|
return resp.Summary, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) GetEndpoints() (map[string]string, error) {
|
||||||
|
err := d.check()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return d.device.GetServices(), nil
|
||||||
|
}
|
||||||
|
func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) ([]Device, error) {
|
||||||
|
// Call a ws-discovery Probe Message to Discover NVT type Devices
|
||||||
|
devices, err := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:" + onvif.NVT.String()}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nvtDevicesSeen := make(map[string]bool)
|
||||||
|
nvtDevices := make([]Device, 0)
|
||||||
|
|
||||||
|
for _, j := range devices {
|
||||||
|
doc := etree.NewDocument()
|
||||||
|
if err := doc.ReadFromString(j); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, xaddr := range doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") {
|
||||||
|
xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2]
|
||||||
|
if !nvtDevicesSeen[xaddr] {
|
||||||
|
dev := NewDevice(onvif.DeviceParams{Xaddr: strings.Split(xaddr, " ")[0]})
|
||||||
|
nvtDevicesSeen[xaddr] = true
|
||||||
|
nvtDevices = append(nvtDevices, *dev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nvtDevices, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Discovery() ([]Device, error) {
|
||||||
|
ifaces, err := listLocalNetworkInterfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
devices := make([]Device, 0)
|
||||||
|
|
||||||
|
for _, iface := range ifaces {
|
||||||
|
idevices, err := GetAvailableDevicesAtSpecificEthernetInterface(iface)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
devices = append(devices, idevices...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func listLocalNetworkInterfaces() ([]string, error) {
|
||||||
|
|
||||||
|
interfaces, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ifaceNames []string
|
||||||
|
for _, iface := range interfaces {
|
||||||
|
// 判断是否为局域网
|
||||||
|
if (iface.Flags&net.FlagUp) == 0 || (iface.Flags&net.FlagRunning) == 0 || (iface.Flags&net.FlagLoopback) != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ifaceNames = append(ifaceNames, iface.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ifaceNames, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
onvif.Xlmns["tse"] = "https://www.onvif.org/ver10/search.wsdl"
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package goonvif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/use-go/onvif"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListInterfaces(t *testing.T) {
|
||||||
|
ifaces, err := listLocalNetworkInterfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(ifaces)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiscovery(t *testing.T) {
|
||||||
|
devices, err := Discovery()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, device := range devices {
|
||||||
|
t.Log(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetCapabilities(t *testing.T) {
|
||||||
|
// 创建一个模拟的 Device 对象
|
||||||
|
d := &Device{
|
||||||
|
DeviceParams: onvif.DeviceParams{
|
||||||
|
Xaddr: "192.168.12.52",
|
||||||
|
Username: "dctdev",
|
||||||
|
Password: "dacenT2017",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试正常情况
|
||||||
|
response, err := d.GetCapabilities()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(response)
|
||||||
|
// 模拟 check 函数返回错误
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetEndpoints(t *testing.T) {
|
||||||
|
// 创建一个模拟的 Device 对象
|
||||||
|
d := &Device{
|
||||||
|
DeviceParams: onvif.DeviceParams{
|
||||||
|
Xaddr: "192.168.12.52",
|
||||||
|
Username: "dctdev",
|
||||||
|
Password: "dacenT2017",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
response, err := d.GetEndpoints()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
t.Log(response)
|
||||||
|
}
|
||||||
|
func TestGetRecordingSummary(t *testing.T) {
|
||||||
|
// 创建一个模拟的 Device 对象
|
||||||
|
d := &Device{
|
||||||
|
DeviceParams: onvif.DeviceParams{
|
||||||
|
Xaddr: "192.168.12.52",
|
||||||
|
Username: "dctdev",
|
||||||
|
Password: "dacenT2017",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
response, err := d.GetRecordingSummary()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
t.Log(response)
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
module git.pyer.club/kingecg/goonvif
|
||||||
|
|
||||||
|
go 1.23.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/beevik/etree v1.1.0 // indirect
|
||||||
|
github.com/elgs/gostrgen v0.0.0-20161222160715-9d61ae07eeae // indirect
|
||||||
|
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||||
|
github.com/juju/errors v0.0.0-20220331221717-b38fca44723b // indirect
|
||||||
|
github.com/rs/zerolog v1.26.1 // indirect
|
||||||
|
github.com/use-go/onvif v0.0.9 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
|
||||||
|
)
|
|
@ -0,0 +1,77 @@
|
||||||
|
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||||
|
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/elgs/gostrgen v0.0.0-20161222160715-9d61ae07eeae h1:3KvK2DmA7TxQ6PZ2f0rWbdqjgJhRcqgbY70bBeE4clI=
|
||||||
|
github.com/elgs/gostrgen v0.0.0-20161222160715-9d61ae07eeae/go.mod h1:wruC5r2gHdr/JIUs5Rr1V45YtsAzKXZxAnn/5rPC97g=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||||
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||||
|
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/juju/errors v0.0.0-20220331221717-b38fca44723b h1:AxFeSQJfcm2O3ov1wqAkTKYFsnMw2g1B4PkYujfAdkY=
|
||||||
|
github.com/juju/errors v0.0.0-20220331221717-b38fca44723b/go.mod h1:jMGj9DWF/qbo91ODcfJq6z/RYc3FX3taCBZMCcpI4Ls=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
|
github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc=
|
||||||
|
github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/use-go/onvif v0.0.9 h1:t6y5uN1LGrdSpNDiy4Vn9HazYgVxdWUBfdBb5cApR7g=
|
||||||
|
github.com/use-go/onvif v0.0.9/go.mod h1:l6K5BgFel7AARm7a9oVj5uvTdwvgttudcP8pUxUf5go=
|
||||||
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:soap-enc="http://www.w3.org/2003/05/soap-encoding"
|
||||||
|
xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
|
||||||
|
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
|
||||||
|
xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
|
||||||
|
xmlns:wsa="http://www.w3.org/2005/08/addressing"
|
||||||
|
xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
|
||||||
|
xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
|
||||||
|
xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
|
||||||
|
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
|
||||||
|
xmlns:tev="http://www.onvif.org/ver10/events/wsdl"
|
||||||
|
xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
|
||||||
|
xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl"
|
||||||
|
xmlns:xop="http://www.w3.org/2004/08/xop/include"
|
||||||
|
xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:onvif="http://www.onvif.org/ver10/schema">
|
||||||
|
<soap-env:Header>
|
||||||
|
<Security
|
||||||
|
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
|
||||||
|
<UsernameToken>
|
||||||
|
<Username>dctdev</Username>
|
||||||
|
<Password
|
||||||
|
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
|
||||||
|
toXf3eaQVUyRYdQVzq91BbfnjTE=</Password>
|
||||||
|
<Nonce
|
||||||
|
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
|
||||||
|
mi9zbm1fihxxb8ypsaq4styjtdtlcwem</Nonce>
|
||||||
|
<Created
|
||||||
|
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
|
||||||
|
2024-10-30T09:32:28.847926976Z</Created>
|
||||||
|
</UsernameToken>
|
||||||
|
</Security>
|
||||||
|
</soap-env:Header>
|
||||||
|
<soap-env:Body>
|
||||||
|
<tds:GetRecordingSummary />
|
||||||
|
</soap-env:Body>
|
||||||
|
</soap-env:Envelope>
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema"
|
||||||
|
xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
|
||||||
|
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
|
||||||
|
xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
|
||||||
|
xmlns:tev="http://www.onvif.org/ver10/events/wsdl"
|
||||||
|
xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl"
|
||||||
|
xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl"
|
||||||
|
xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error"
|
||||||
|
xmlns:dn="http://www.onvif.org/ver10/network/wsdl"
|
||||||
|
xmlns:tns1="http://www.onvif.org/ver10/topics"
|
||||||
|
xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl"
|
||||||
|
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl"
|
||||||
|
xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12"
|
||||||
|
xmlns:http="http://schemas.xmlsoap.org/wsdl/http"
|
||||||
|
xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery"
|
||||||
|
xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||||
|
xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing"
|
||||||
|
xmlns:wstop="http://docs.oasis-open.org/wsn/t-1"
|
||||||
|
xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
|
||||||
|
xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
|
||||||
|
xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
|
||||||
|
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
|
||||||
|
xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
|
||||||
|
xmlns:trc="http://www.onvif.org/ver10/recording/wsdl"
|
||||||
|
xmlns:tse="http://www.onvif.org/ver10/search/wsdl"
|
||||||
|
xmlns:trp="http://www.onvif.org/ver10/replay/wsdl"
|
||||||
|
xmlns:tnshik="http://www.hikvision.com/2011/event/topics"
|
||||||
|
xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl"
|
||||||
|
xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema"
|
||||||
|
xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl"
|
||||||
|
xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"
|
||||||
|
xmlns:axt="http://www.onvif.org/ver20/analytics">
|
||||||
|
<env:Body>
|
||||||
|
<tse:GetRecordingSummaryResponse>
|
||||||
|
<tse:Summary>
|
||||||
|
<tt:DataFrom>2024-10-16T01:03:32Z</tt:DataFrom>
|
||||||
|
<tt:DataUntil>2024-10-30T09:41:47Z</tt:DataUntil>
|
||||||
|
<tt:NumberRecordings>1</tt:NumberRecordings>
|
||||||
|
</tse:Summary>
|
||||||
|
</tse:GetRecordingSummaryResponse>
|
||||||
|
</env:Body>
|
||||||
|
</env:Envelope>
|
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (c) 2022 Jean-Francois SMIGIELSKI
|
||||||
|
// Distributed under the MIT License
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mainTemplate = `// Code generated : DO NOT EDIT.
|
||||||
|
// Copyright (c) 2022 Jean-Francois SMIGIELSKI
|
||||||
|
// Distributed under the MIT License
|
||||||
|
|
||||||
|
package {{.Package}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/juju/errors"
|
||||||
|
"github.com/use-go/onvif"
|
||||||
|
"github.com/use-go/onvif/sdk"
|
||||||
|
"git.pyer.club/kingecg/goonvif/{{.StructPackage}}"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Call_{{.TypeRequest}} forwards the call to dev.CallMethod() then parses the payload of the reply as a {{.TypeReply}}.
|
||||||
|
func Call_{{.TypeRequest}}(ctx context.Context, dev *onvif.Device, request {{.StructPackage}}.{{.TypeRequest}}) ({{.StructPackage}}.{{.TypeReply}}, error) {
|
||||||
|
type Envelope struct {
|
||||||
|
Header struct{}
|
||||||
|
Body struct {
|
||||||
|
{{.TypeReply}} {{.StructPackage}}.{{.TypeReply}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var reply Envelope
|
||||||
|
if httpReply, err := dev.CallMethod(request); err != nil {
|
||||||
|
return reply.Body.{{.TypeReply}}, errors.Annotate(err, "call")
|
||||||
|
} else {
|
||||||
|
err = sdk.ReadAndParse(ctx, httpReply, &reply, "{{.TypeRequest}}")
|
||||||
|
return reply.Body.{{.TypeReply}}, errors.Annotate(err, "reply")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
type parserEnv struct {
|
||||||
|
Package string
|
||||||
|
StructPackage string
|
||||||
|
TypeReply string
|
||||||
|
TypeRequest string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
env := parserEnv{
|
||||||
|
Package: flag.Arg(0),
|
||||||
|
StructPackage: flag.Arg(1),
|
||||||
|
TypeRequest: flag.Arg(2),
|
||||||
|
TypeReply: flag.Arg(2) + "Response",
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(env)
|
||||||
|
|
||||||
|
body, err := template.New("body").Parse(mainTemplate)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fout, err := os.Create(env.TypeRequest + "_auto.go")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
defer fout.Close()
|
||||||
|
|
||||||
|
err = body.Execute(fout, &env)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Code generated : DO NOT EDIT.
|
||||||
|
// Copyright (c) 2022 Jean-Francois SMIGIELSKI
|
||||||
|
// Distributed under the MIT License
|
||||||
|
|
||||||
|
package search
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/juju/errors"
|
||||||
|
"github.com/use-go/onvif"
|
||||||
|
"github.com/use-go/onvif/sdk"
|
||||||
|
"git.pyer.club/kingecg/goonvif/search"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Call_GetRecordingSummary forwards the call to dev.CallMethod() then parses the payload of the reply as a GetRecordingSummaryResponse.
|
||||||
|
func Call_GetRecordingSummary(ctx context.Context, dev *onvif.Device, request search.GetRecordingSummary) (search.GetRecordingSummaryResponse, error) {
|
||||||
|
type Envelope struct {
|
||||||
|
Header struct{}
|
||||||
|
Body struct {
|
||||||
|
GetRecordingSummaryResponse search.GetRecordingSummaryResponse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var reply Envelope
|
||||||
|
if httpReply, err := dev.CallMethod(request); err != nil {
|
||||||
|
return reply.Body.GetRecordingSummaryResponse, errors.Annotate(err, "call")
|
||||||
|
} else {
|
||||||
|
err = sdk.ReadAndParse(ctx, httpReply, &reply, "GetRecordingSummary")
|
||||||
|
return reply.Body.GetRecordingSummaryResponse, errors.Annotate(err, "reply")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package search
|
||||||
|
|
||||||
|
import (
|
||||||
|
xsd "github.com/use-go/onvif/xsd"
|
||||||
|
onvifmodel "github.com/use-go/onvif/xsd/onvif"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SourceReference onvifmodel.ReferenceToken
|
||||||
|
type RecordingReference onvifmodel.ReferenceToken
|
||||||
|
|
||||||
|
type SearchScope struct {
|
||||||
|
IncludedSources []SourceReference `xml:"onvif:IncludedSources"`
|
||||||
|
IncludedRecordings []RecordingReference `xml:"onvif:IncludedRecordings"`
|
||||||
|
RecordingInformationFilter xsd.String `xml:"onvif:RecordingInformationFilter"`
|
||||||
|
Extension SearchScopeExtension `xml:"onvif:Extension"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchScopeExtension []xsd.AnyType
|
||||||
|
|
||||||
|
type FindingRecordings struct {
|
||||||
|
XMLName string `xml:"tse:FindingRecordings"`
|
||||||
|
Scope SearchScope `xml:"tse:Scope"`
|
||||||
|
MaxMatches xsd.Int `xml:"tse:MaxMatches"`
|
||||||
|
KeepAliveTimeout xsd.Duration `xml:"tse:KeepAliveTimeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetRecordingSummary struct {
|
||||||
|
XMLName string `xml:"tse:GetRecordingSummary"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecordingSummary struct {
|
||||||
|
DataFrom xsd.DateTime
|
||||||
|
DataUntil xsd.DateTime
|
||||||
|
NumberRecordings xsd.Int
|
||||||
|
}
|
||||||
|
type GetRecordingSummaryResponse struct {
|
||||||
|
Summary RecordingSummary
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package search
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
xsd "github.com/use-go/onvif/xsd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMarshallSummary(t *testing.T) {
|
||||||
|
summary := RecordingSummary{
|
||||||
|
DataFrom: xsd.DateTime("2019-01-01T00:00:00Z"),
|
||||||
|
DataUntil: xsd.DateTime("2019-01-01T00:00:00Z"),
|
||||||
|
NumberRecordings: xsd.Int(1),
|
||||||
|
}
|
||||||
|
b, err := xml.Marshal(summary)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshallSummary(t *testing.T) {
|
||||||
|
data := `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema"
|
||||||
|
xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
|
||||||
|
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
|
||||||
|
xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
|
||||||
|
xmlns:tev="http://www.onvif.org/ver10/events/wsdl"
|
||||||
|
xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl"
|
||||||
|
xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl"
|
||||||
|
xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error"
|
||||||
|
xmlns:dn="http://www.onvif.org/ver10/network/wsdl"
|
||||||
|
xmlns:tns1="http://www.onvif.org/ver10/topics"
|
||||||
|
xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl"
|
||||||
|
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl"
|
||||||
|
xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12"
|
||||||
|
xmlns:http="http://schemas.xmlsoap.org/wsdl/http"
|
||||||
|
xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery"
|
||||||
|
xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||||
|
xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing"
|
||||||
|
xmlns:wstop="http://docs.oasis-open.org/wsn/t-1"
|
||||||
|
xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
|
||||||
|
xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
|
||||||
|
xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
|
||||||
|
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
|
||||||
|
xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
|
||||||
|
xmlns:trc="http://www.onvif.org/ver10/recording/wsdl"
|
||||||
|
xmlns:tse="http://www.onvif.org/ver10/search/wsdl"
|
||||||
|
xmlns:trp="http://www.onvif.org/ver10/replay/wsdl"
|
||||||
|
xmlns:tnshik="http://www.hikvision.com/2011/event/topics"
|
||||||
|
xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl"
|
||||||
|
xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema"
|
||||||
|
xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl"
|
||||||
|
xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"
|
||||||
|
xmlns:axt="http://www.onvif.org/ver20/analytics">
|
||||||
|
<env:Body>
|
||||||
|
<tse:GetRecordingSummaryResponse>
|
||||||
|
<tse:Summary>
|
||||||
|
<tt:DataFrom>2024-10-16T01:03:32Z</tt:DataFrom>
|
||||||
|
<tt:DataUntil>2024-10-30T09:41:47Z</tt:DataUntil>
|
||||||
|
<tt:NumberRecordings>1</tt:NumberRecordings>
|
||||||
|
</tse:Summary>
|
||||||
|
</tse:GetRecordingSummaryResponse>
|
||||||
|
</env:Body>
|
||||||
|
</env:Envelope>`
|
||||||
|
type Envelope struct {
|
||||||
|
Header struct{}
|
||||||
|
Body struct {
|
||||||
|
GetRecordingSummaryResponse GetRecordingSummaryResponse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var reply Envelope
|
||||||
|
// var reply GetRecordingSummaryResponse
|
||||||
|
err := xml.Unmarshal([]byte(data), &reply)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(reply)
|
||||||
|
}
|
Loading…
Reference in New Issue