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" }