vnpt_onvif 1.0.4 copy "vnpt_onvif: ^1.0.4" to clipboard
vnpt_onvif: ^1.0.4 copied to clipboard

A professional, native ONVIF manager library for Flutter, ported from ODM to support device discovery, SOAP/WS-Security, and RTSP stream acquisition.

vnpt_onvif #

Thư viện Flutter để giao tiếp với thiết bị ONVIF (camera IP). Hỗ trợ discovery mạng LAN, xác thực WS-Security (Digest), và đầy đủ các thao tác quản lý camera qua SOAP/XML thuần.


Cài đặt #

dependencies:
  vnpt_onvif:
    path: ../vnpt_onvif   # hoặc git: { url: ... }
import 'package:vnpt_onvif/vnpt_onvif.dart';

Kiến trúc #

OnvifClient              ← HTTP/SOAP + WS-Security (Digest)
    │
    ├── DeviceService    ← Device management (tds)
    ├── DeviceIoService  ← Device I/O – relay outputs (tmd)
    ├── ImagingService   ← Imaging settings – IR cut, exposure (timg)
    ├── MediaService     ← Profiles, stream URIs, video sources (trt)
    └── PtzService       ← PTZ movement, auxiliary commands (tptz)

Tạo client #

final client = OnvifClient(
  xaddr: 'http://192.168.1.100/onvif/device_service',
  username: 'admin',
  password: 'password',
);

Client xử lý tự động:

  • Sinh Nonce ngẫu nhiên mỗi request
  • Tính PasswordDigest (Base64(SHA1(nonce + created + password)))
  • Đồng bộ thời gian lệch qua timeOffset

Discovery #

final discovery = OnvifDiscovery();

discovery.deviceStream.listen((device) {
  print('${device.name} – ${device.xAddrs.first}');
});

await discovery.probe();

DeviceService #

Quản lý thiết bị qua ONVIF Device Management Service (tds).

final service = DeviceService(client);

Thông tin thiết bị #

Method Trả về Mô tả
getDeviceInformation() Map<String, String> Manufacturer, Model, Serial, Firmware, HardwareId
getSystemDateAndTime() DateTime Thời gian UTC hiện tại trên thiết bị
getServiceUrls() Map<String, String> URL của từng service (Device, Media, PTZ, DeviceIO, ...)
final info = await service.getDeviceInformation();
// → {Manufacturer: HeroSpeed, Model: IPCamera, ...}

final urls = await service.getServiceUrls();
// → {Media: http://192.168.1.100/onvif/media_service, PTZ: ..., DeviceIO: ...}

Relay Output #

Method Trả về Mô tả
getRelayOutputs() List<String> Danh sách token relay output
setRelayOutputState(token, active) void Bật/tắt relay output
final tokens = await service.getRelayOutputs();
// → ['RelayOutputs0']

await service.setRelayOutputState(tokens.first, active: true);
await Future.delayed(Duration(seconds: 2));
await service.setRelayOutputState(tokens.first, active: false);

Cấu hình mạng #

Method Trả về Mô tả
getNetworkInterfaces() List<OnvifNetworkInterface> Danh sách interface với IP, subnet, DHCP mode
setNetworkInterfaces(token, ip, prefixLength) bool rebootNeeded Đặt IP tĩnh trên interface
getNetworkDefaultGateway() String? Gateway hiện tại
setNetworkDefaultGateway(ip) void Đặt gateway
setDhcp(token) bool rebootNeeded Chuyển sang chế độ DHCP
setDns(addresses) void Đặt DNS server thủ công
systemReboot() void Khởi động lại thiết bị

Lưu ý: setNetworkInterfaces, setDhcp, setStaticIp đều trả về rebootNeeded. Gọi systemReboot() theo ý muốn sau khi đã thực hiện các thao tác cần thiết (ví dụ: cập nhật backend).

Convenience method – đặt IP tĩnh

final interfaces = await service.getNetworkInterfaces();
final token = interfaces.first.token;

// setStaticIp = setNetworkInterfaces + setNetworkDefaultGateway
// trả về rebootNeeded, KHÔNG tự reboot
final rebootNeeded = await service.setStaticIp(
  interfaceToken: token,
  ip: '192.168.1.100',
  prefixLength: 24,   // 24 = 255.255.255.0
  gateway: '192.168.1.1',
);

// Thực hiện các thao tác trước khi reboot tại đây
// (ví dụ: cập nhật backend)

if (rebootNeeded) await service.systemReboot();
// → Kết nối mất sau dòng này

Chuyển về DHCP

final interfaces = await service.getNetworkInterfaces();
final rebootNeeded = await service.setDhcp(interfaces.first.token);

// Cập nhật backend (xóa IP cũ) trước khi reboot
if (rebootNeeded) await service.systemReboot();

ImagingService #

Điều khiển các thiết lập hình ảnh qua Imaging Service (timg).

final imaging = ImagingService(
  OnvifClient(xaddr: 'http://192.168.1.100/onvif/imaging_service', ...),
);

IR Cut Filter #

enum OnvifIrCutFilter { on, off, auto }
Method Trả về Mô tả
getIrCutFilter(videoSourceToken) OnvifIrCutFilter? Trạng thái IR cut filter hiện tại
setIrCutFilter(videoSourceToken, mode) void Đặt trạng thái IR cut filter
// Lấy video source token
final sources = await MediaService(client).getVideoSources();
final vsToken = sources.first;

// Đọc trạng thái hiện tại
final current = await imaging.getIrCutFilter(vsToken);
// → OnvifIrCutFilter.auto

// Toggle: ON (ban ngày) / OFF (ban đêm – bật đèn IR)
final next = current == OnvifIrCutFilter.on
    ? OnvifIrCutFilter.off
    : OnvifIrCutFilter.on;
await imaging.setIrCutFilter(vsToken, next);

Mô tả giá trị:

  • ON → filter IR cut bật → chế độ ban ngày, đèn IR tắt
  • OFF → filter IR cut tắt → chế độ ban đêm, đèn IR bật (nếu đủ tối)
  • AUTO → camera tự quyết theo ánh sáng môi trường

MediaService #

final media = MediaService(client);
Method Trả về Mô tả
getProfiles() List<OnvifProfile> Danh sách profile (token + name)
getVideoSources() List<String> Danh sách VideoSource token
getStreamUri(profileToken) String RTSP stream URI
final profiles = await media.getProfiles();
final streamUri = await media.getStreamUri(profiles.first.token);
// → rtsp://admin:password@192.168.1.100/stream1

final videoSources = await media.getVideoSources();
// → ['VideoSource_1']

PtzService #

final ptz = PtzService(
  OnvifClient(xaddr: 'http://192.168.1.100/onvif/ptz_service', ...),
);
Method Trả về Mô tả
continuousMove(token, panSpeed, tiltSpeed, zoomSpeed) void Di chuyển liên tục theo tốc độ (-1.0 đến 1.0)
stop(token) void Dừng di chuyển
sendAuxiliaryCommand(token, data) void Gửi lệnh phụ trợ
final token = profiles.first.token;

// Pan phải 0.6s rồi trả về
await ptz.continuousMove(token, panSpeed: 0.4);
await Future.delayed(Duration(milliseconds: 600));
await ptz.stop(token);
await Future.delayed(Duration(milliseconds: 300));
await ptz.continuousMove(token, panSpeed: -0.4);
await Future.delayed(Duration(milliseconds: 600));
await ptz.stop(token);

Auxiliary Commands phổ biến

Data Chức năng
tt:IRLamp|on Bật đèn IR (nếu camera hỗ trợ)
tt:IRLamp|off Tắt đèn IR
tt:IRLamp|auto IR chế độ tự động
tt:Wiper|on Bật gạt nước (outdoor camera)
// Thử bật đèn IR qua auxiliary command
try {
  await ptz.sendAuxiliaryCommand(token, 'tt:IRLamp|on');
} catch (_) {
  // Không phải camera nào cũng hỗ trợ
}

DeviceIoService #

Điều khiển I/O qua Device IO Service (tmd). Endpoint thường là /onvif/deviceio_service hoặc cổng khác (lấy từ getServiceUrls()).

final deviceIoUrl = (await DeviceService(client).getServiceUrls())['DeviceIO']
    ?? 'http://192.168.1.100/onvif/deviceio_service';

final ioService = DeviceIoService(
  OnvifClient(xaddr: deviceIoUrl, ...),
);
Method Trả về Mô tả
setRelayOutputSettings(token, mode, delayTime, idleState) void Cấu hình relay (Monostable/Bistable, delay, idle state)
setRelayOutputState(token, active) void Bật/tắt relay qua DeviceIO
// Cấu hình Monostable 5 giây rồi trigger
await ioService.setRelayOutputSettings(
  'RELAY_OUTPUT_000',
  mode: 'Monostable',   // tự reset sau delayTime
  delayTime: 'PT5S',    // ISO 8601: 5 giây
  idleState: 'open',    // trạng thái mặc định khi idle
);
await ioService.setRelayOutputState('RELAY_OUTPUT_000', active: true);

Models #

OnvifNetworkInterface #

Field Type Mô tả
token String Dùng cho setNetworkInterfaces, setDhcp
enabled bool Interface có đang bật không
dhcp bool true nếu đang dùng DHCP
ipv4Address String? IP hiện tại (manual hoặc từ DHCP)
prefixLength int? Subnet prefix (24 = 255.255.255.0)
hwAddress String? MAC address

OnvifNetworkConfig #

Model tổng hợp từ getNetworkInterfaces() + getNetworkDefaultGateway():

Field Type Mô tả
interfaceToken String Token dùng để set lại
ip String IP hiện tại
prefixLength int Subnet prefix
gateway String Gateway hiện tại
isDhcp bool Đang dùng DHCP hay IP tĩnh

Logging #

Thư viện dùng OnvifLogger để log mọi request/response. Mặc định dùng dart:developer.log.

// Tích hợp với hệ thống log của app
OnvifLogger.initialize((message, {name}) {
  print('[$name] $message');
  // hoặc Firebase, Sentry, v.v.
});

Mỗi service log theo format:

[DeviceService] GetNetworkInterfaces count=1 eth0:192.168.1.100/24 dhcp=false
[PtzService] ContinuousMove token=Profile_1 pan=0.4 tilt=0.0 zoom=0.0
[ImagingService] SetImagingSettings OK IrCutFilter=OFF videoSource=VideoSource_1

Quyền hạn #

Android – thêm vào AndroidManifest.xml:

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>

iOS – thêm vào Info.plist:

<key>NSLocalNetworkUsageDescription</key>
<string>Cần quyền truy cập mạng nội bộ để tìm kiếm camera ONVIF</string>

Và đăng ký Multicast Entitlement với Apple.


Changelog #

Added #

  • ImagingServicegetIrCutFilter, setIrCutFilter, enum OnvifIrCutFilter
  • PtzServicecontinuousMove, stop, sendAuxiliaryCommand
  • DeviceIoServicesetRelayOutputSettings, setRelayOutputState (tmd namespace)
  • MediaServicegetVideoSources
  • DeviceServicegetRelayOutputs, setRelayOutputState, getServiceUrls, getNetworkInterfaces, setNetworkInterfaces, setNetworkDefaultGateway, getNetworkDefaultGateway, setDhcp, setDns, setStaticIp (convenience), systemReboot
  • Model OnvifNetworkInterface, OnvifNetworkConfig
  • Logging đầy đủ cho tất cả service methods qua OnvifLogger

Changed #

  • setStaticIpsetDhcp không tự động reboot — trả về bool rebootNeeded để caller kiểm soát timing (ví dụ: cập nhật backend trước khi reboot)
0
likes
150
points
112
downloads

Documentation

API reference

Publisher

verified publishertamdv.site

Weekly Downloads

A professional, native ONVIF manager library for Flutter, ported from ODM to support device discovery, SOAP/WS-Security, and RTSP stream acquisition.

Repository (GitHub)
View/report issues

License

GPL-2.0 (license)

Dependencies

crypto, flutter, http, intl, xml

More

Packages that depend on vnpt_onvif