Comments (6)
Hi @Viper-Bit ,
Per the WS-Discovery spec - https://en.wikipedia.org/wiki/WS-Discovery#:~:text=Web%20Services%20Dynamic%20Discovery%20(WS,255.250%20or%20FF02%3A%3AC.
"Web Services Dynamic Discovery (WS-Discovery) is a technical specification that defines a multicast discovery protocol to locate services on a local network. It operates over TCP and UDP port 3702 and uses IP multicast address 239.255.255.250 or FF02::C. As the name suggests, the actual communication between nodes is done using web services standards, notably SOAP-over-UDP."
Are you running the code on Windows, maybe the Windows firewall is blocking the connection. I don't think this is a code related issue.
from easy_onvif.
@faithoflifedev thx for answer,
with disabled firewall still get same result
i think dart have a problem to create dgram socket on windows with virtual adapters, i wrote a c++ WS-Discovery and use it as a dll in dart in same pc and everything works like charm.
and found similar issue in flutter repo #53477
from easy_onvif.
Thanks for the update @Viper-Bit, I tried the work-arounds suggested in #53477 and none worked for me on Windows 11.
Are you able to provide your c++ code and I can look at incorporating it into this package until a better solution is available?
from easy_onvif.
@faithoflifedev yes OfCourse,
onvif.cpp
#include "onvif.h"
char preferred_network_address[16];
int setSocketOptions(int socket) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500000;
int broadcast = 500;
char loopch = 0;
int status = 0;
struct in_addr localInterface;
#ifdef _WIN32
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
IN_ADDR IPAddr;
pIPAddrTable = (MIB_IPADDRTABLE*)malloc(sizeof(MIB_IPADDRTABLE));
if (pIPAddrTable) {
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
free(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE*)malloc(dwSize);
}
if (pIPAddrTable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
return -1;
}
}
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
printf("GetIpAddrTable failed with error %d\n", dwRetVal);
return -1;
}
int p = 0;
while (p < (int)pIPAddrTable->dwNumEntries) {
IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[p].dwAddr;
IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[p].dwMask;
if (pIPAddrTable->table[p].dwAddr != inet_addr("127.0.0.1") && pIPAddrTable->table[p].dwMask == inet_addr("255.255.255.0")) {
if (strlen(preferred_network_address) > 0) {
localInterface.s_addr = inet_addr(preferred_network_address);
}
else {
localInterface.s_addr = pIPAddrTable->table[p].dwAddr;
}
status = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&localInterface, sizeof(localInterface));
if (status < 0)
printf("ip_multicast_if error");
p = (int)pIPAddrTable->dwNumEntries;
}
p++;
}
if (pIPAddrTable) {
free(pIPAddrTable);
pIPAddrTable = NULL;
}
status = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&broadcast, sizeof(broadcast));
#else
if (strlen(preferred_network_address) > 0) {
localInterface.s_addr = inet_addr(preferred_network_address);
status = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&localInterface, sizeof(localInterface));
if (status < 0)
printf("ip_multicast_if error");
}
status = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval*)&tv, sizeof(struct timeval));
#endif
status = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&loopch, sizeof(loopch));
return 0;
}
int discovery(OnvifDiscoveryData* data, const char * probeMessage, int duration) {
#ifdef _WIN32
WSADATA wsaData;
int wsaStartup = WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
sockaddr_in broadcast_address = {};
int broadcast_message_length = strlen(probeMessage);
int broadcast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setSocketOptions(broadcast_socket);
memset((char*)&broadcast_address, 0, sizeof(broadcast_address));
broadcast_address.sin_family = AF_INET;
broadcast_address.sin_port = htons(3702);
broadcast_address.sin_addr.s_addr = inet_addr("239.255.255.250");
int status = sendto(broadcast_socket, probeMessage, broadcast_message_length, 0, (struct sockaddr*)&broadcast_address, sizeof(broadcast_address));
if (status < 0) {
//error
}
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
int i = 0;
bool loop = true;
socklen_t address_size = sizeof(broadcast_address);
while (loop) {
int len = recvfrom(broadcast_socket, data->buf[i], sizeof(data->buf[i]), 0, (struct sockaddr*)&broadcast_address, &address_size);
if (len > 0) {
i++;
}
else {
loop = false;
if (len < 0) {
//error
}
}
}
#ifdef _WIN32
closesocket(broadcast_socket);
WSACleanup();
#else
close(broadcast_socket);
#endif
return i;
}
onvif.h
#ifndef ONVIF_H
#define ONVIF_H
#include <chrono>
#include <thread>
#include <cstring>
#ifdef _WIN32
#define LIBRARY_API __declspec(dllexport)
#include <ws2tcpip.h>
#include <iphlpapi.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#else
#define LIBRARY_API
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#ifdef __MINGW32__
#include <ws2tcpip.h>
#endif
#pragma pack (push, 1)
struct OnvifDiscoveryData {
char buf[128][8192];
};
#pragma pack(pop)
#ifdef __cplusplus
extern "C" {
#endif
LIBRARY_API int discovery(OnvifDiscoveryData* data, const char* probeMessage, int duration);
#ifdef __cplusplus
}
#endif
#endif
and dart side is:
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
final Pointer<T> Function<T extends NativeType>(String symbolName) _lookup =
() {
if (Platform.isWindows) {
return DynamicLibrary.open('onvif.dll').lookup;
} else if (Platform.isLinux) {
return DynamicLibrary.open('/usr/local/lib/libonvif.so').lookup;
} else {
throw UnimplementedError();
}
}();
final _discoveryPtr = _lookup<
NativeFunction<
Int32 Function(
Pointer<NativeType>,
Pointer<NativeType>,
Int32,
)>>('discovery');
final _discovery = _discoveryPtr.asFunction<
int Function(
Pointer<NativeType>,
Pointer<NativeType>,
int,
)>();
@Packed(1)
sealed class _OnvifDiscoveryData extends Struct {
@Array<Int8>(128, 8192)
external Array<Array<Int8>> buf;
}
const _probeMessage = '''
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<SOAP-ENV:Header>
<a:Action SOAP-ENV:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>
<a:MessageID>urn:uuid:2809d092-cb6c-476a-9a6f-7ee0123265d3</a:MessageID>
<a:ReplyTo>
<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
</a:ReplyTo>
<a:To SOAP-ENV:mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<p:Probe xmlns:p="http://schemas.xmlsoap.org/ws/2005/04/discovery">
<d:Types xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</d:Types>
</p:Probe>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
''';
Future<void> discovery([Duration duration = const Duration(seconds: 5)]) async {
final data = calloc<_OnvifDiscoveryData>();
final probeMessageData = _probeMessage.toNativeUtf8();
final devices = _discovery(data, probeMessageData, duration.inMilliseconds);
//for flutter _discovery cant be called in main thread (locks main thread for duration) so _discovery must be called from isolate
/*
final devices = await compute(
(msg) {
return _discovery(
Pointer.fromAddress(msg['dataAddress'] as int),
Pointer.fromAddress(msg['probeAddress'] as int),
msg['duration'] as int,
);
},
{
'dataAddress': data.address,
'probeAddress': probeMessageData.address,
'duration': duration.inMilliseconds,
},
);
*/
print('Found $devices Devices');
for (var index = 0; index < devices; index++) {
print(Pointer.fromAddress(data.address + index * 8192)
.cast<Utf8>()
.toDartString());
}
malloc.free(probeMessageData);
calloc.free(data);
}
from easy_onvif.
Hi @Viper-Bit , as an update on this, I'm currently readying a new release with the above workaround for Windows OS included. It should be available in a day or two. Thanks for your help with this.
from easy_onvif.
Hi @Viper-Bit , I've just published the new package v2.1.3+1.
Please let me know if this resolves the issue for you, or if you need a better explanation on how to use the fix (see the known issues
section of the README).
from easy_onvif.
Related Issues (20)
- [2.1.0-dev11] error during onvif.getProfiles() device media1 HOT 2
- [2.1.0-dev11] error during onvif.getStreamUri() device media1 HOT 2
- [2.1.0-dev.14] onvif.mediaSupportLevel HOT 2
- Flutter example application cannot run successfully HOT 2
- RTSP port in the getStreamUri response not correct HOT 3
- camera recording HOT 2
- Is it possible to check if Onvif connect failed? HOT 2
- Onvif Imaging Profile HOT 3
- MulticastProbe with Auth HOT 3
- using CLI for testing causes a crash on onvif probe list-devices HOT 1
- Unable to get preset HOT 26
- new specifications support--thermal interface HOT 2
- How send audio stream to camera ? HOT 3
- Couldn't connect with Ezviz H8c camera HOT 3
- BUG: get-capabilities method is breaking for some cameras HOT 4
- BUG: Camera movement command is not working for some cameras HOT 16
- DioException [receive timeout]: The request HOT 10
- getStreamUri doesn't connect to sub stream of Onvif camera HOT 5
- Actions that require authentication no longer work HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from easy_onvif.