smart_device_core
A Flutter Plugin that provides core smart device management capabilities for Android and iOS, including device binding, live video streaming, event library, bird recognition, device settings, and more.
Requirements
- Flutter >= 3.3.0
- Dart SDK >= 3.0.5 < 4.0.0
- Android: minSdkVersion 21+
- iOS: 13.0+
Installation
Add the dependency in your pubspec.yaml:
dependencies:
smart_device_core:
git:
url: https://github.com/SmartIotDeviceSDK/flutter.git
Quick Start
1. Initialize SDK
import 'package:smart_device_core/smart_device_core.dart';
final config = InitConfigBuilder()
.setTenantId('your_tenant_id')
.setLanguage('en')
.setIsDebug(true)
.setLoggerDelegate(LoggerDelegate(
error: (tag, msg) => print('[$tag] ERROR: $msg'),
info: (tag, msg) => print('[$tag] INFO: $msg'),
))
.setAccountChangeListener(AccountChangeListener(
onAccountInfoError: (status) {
// Handle account errors, e.g. token expiration
},
))
.build();
SmartDeviceCore.getInstance()?.initSDK(config, Callback(
onSuccess: (code, msg, data) => print('SDK initialized successfully'),
onError: (code, msg) => print('SDK initialization failed: $msg'),
));
2. Login
SmartDeviceCore.getInstance()?.login('your_jwt_token', Callback(
onSuccess: (code, msg, data) => print('Login successful'),
onError: (code, msg) => print('Login failed: $msg'),
));
Core Modules
BindCore - Device Binding
Supports multiple binding methods: QR code, wired, AP hotspot, and Bluetooth (BLE).
final bindCore = BindCore.getInstance();
// Initialize Bluetooth
bindCore?.bleInit();
// Discover devices via BLE
bindCore?.discoverDeviceByBLE(DiscoverCallBack(
onDiscover: (device) => print('Device found: $device'),
));
// Bind via Bluetooth
bindCore?.startBindByBLE('WiFi_SSID', 'WiFi_Password', 'device_user_sn',
StartBindCallback(
onBindProgress: (step, code) => print('Binding progress: $step'),
onBindSuccess: (device) => print('Binding successful'),
onBindFailed: (code, msg) => print('Binding failed: $msg'),
),
);
// Bind via QR code
bindCore?.startBindByQRCode('WiFi_SSID', 'WiFi_Password',
StartBindCallback(...),
);
// Bind via wired connection
bindCore?.startBindByWire('device_user_sn', StartBindCallback(...));
// Get WiFi list scanned by the device
bindCore?.getScanedWifiListOverA4xBle('ble_identifier', 'user_sn', Callback(...));
// Stop binding / release resources
bindCore?.stopBind();
bindCore?.releaseBindResource();
DeviceManageCore - Device Management
final deviceCore = DeviceManageCore.getInstance();
// Query device list
deviceCore?.queryDeviceList(
onSuccess: (code, msg, devices) {
for (var device in devices) {
print('Device: ${device.serialNumber}');
}
},
onError: (code, msg) => print('Query failed: $msg'),
);
// Query single device info
deviceCore?.querySingleDeviceInfo('serial_number',
onSuccess: (code, msg, device) => print('Device name: ${device.name}'),
onError: (code, msg) => print('Query failed: $msg'),
);
DeviceSettingCore - Device Settings
final settingCore = DeviceSettingCore.getInstance();
// Get device attributes
settingCore?.getAttribute('serial_number',
onSuccess: (code, msg, attributes) => print('Attributes: $attributes'),
onError: (code, msg) => print('Failed to get attributes: $msg'),
);
// Set motion tracking
settingCore?.setMotionTrack('serial_number', true,
onSuccess: (code, msg, data) => print('Setting applied'),
onError: (code, msg) => print('Setting failed: $msg'),
);
DeviceSleepPlanCore - Sleep Schedule
DeviceSleepPlanCore.getInstance()?.setSleep('serial_number', true,
onSuccess: (code, msg, data) => print('Sleep schedule set'),
onError: (code, msg) => print('Setting failed: $msg'),
);
Live Video
Use LiveManagerInstance to get a player instance. Supports both WebRTC and IJK playback (automatically selected based on device type).
// Get player
final player = LiveManagerInstance().getPlayer(deviceBean);
// Add rendering view in Widget
SurfaceView(serialNumber: 'device_serial_number')
// Start live streaming
player?.startLive(customParam);
// Audio / Intercom
player?.audioEnable(true);
player?.speakEnable(true);
// Screenshot
player?.screenShot(
onSuccess: (code, msg, imageBytes) => print('Screenshot captured'),
onError: (code, msg) => print('Screenshot failed'),
);
// PTZ control
player?.setPtz(x, y,
onSuccess: (code, msg, data) {},
onError: (code, msg) {},
);
// Switch resolution
player?.setResolution(getVideoResolutionValue(VideoResolution.VIDEO_SIZE_1280x720),
onSuccess: (code, msg, data) {},
onError: (code, msg) {},
);
// SD card playback
player?.getSDVideoList(startTime, endTime,
onSuccess: (code, msg, videoList) {},
onError: (code, msg) {},
);
player?.startSdcard(startTime);
// Stop live streaming / release resources
player?.stopLive();
player?.destroyLive();
High Frame Rate (Slow Motion), Playback Speed & Slow-Motion Download
Devices that support high frame rate record at 60/120 fps; clips are played back at ½x / ¼x / ⅛x for a slow-motion effect. Full reference (Chinese): doc/video_playback.md.
// 1. Capability — values are `<width>x<height>@<fps>`; normalize the `720P@60`
// shorthand some devices report, then de-duplicate.
final support = device.deviceSupport; // support.supportHighFramerate == 1
final hfrOptions = (support?.supportHighFramerateResolution ?? const <String>[])
.map(normalizeResolutionValue)
.toSet()
.toList(); // e.g. ['1280x720@60', '1920x1080@120']
// 2. Enable an HFR resolution (the device turns HDR/WDR off while HFR is on)
DeviceSettingCore.getInstance()?.updateAttribute(sn, 'videoResolution', '1280x720@60',
onSuccess: (int code, String msg, dynamic data) {},
onError: (int code, String msg) {},
);
// 3. List slow-motion clips only
final entry = FilterEntry()
..serialNumbers = [sn]
..highFramerate = 1;
LibraryCore.getInstance()?.getEventRecordByFilter(entry,
onSuccess: (int code, String msg, LibraryEventDatabean? data) {
for (final e in data?.list ?? const <RecordEventBean>[]) {
// [1x, ½x, ¼x] at 60 fps, plus ⅛x at 120 fps; [1x] otherwise
final speeds = PlaybackSpeed.supportedSpeeds(framerate: e.framerate);
}
},
onError: (int code, String msg) {},
);
// 4. Download / export a clip at ½x (the native SDK drops the audio track when speed != 1x)
LibraryCore.getInstance()?.downloadSource(tasks, false, speedRatio: 0.5,
onProgress: (int downloadIndex, int total, double progress) {},
onFinish: (bool result, List<String?>? sharePathList) {},
);
// 5. Live: the device locks resolution switching while it records slow motion
@override
void onDeviceMsgPush(int code, Object obj) {
if (code == LiveStateListener.DEVICE_MSG_CAN_CHANGE_RESOLUTION && obj == false) {
// disable your resolution selector until the next `true`
}
}
Notes
- Playback speed is applied by your own file player (
ijkplayer.setSpeed/AVPlayer.rate); this plugin ships no cloud/SD-card file playback player. It provides the speed-option algorithm (PlaybackSpeed.supportedSpeeds) and the clip metadata (framerate/highFramerate) only. Native apps mute the audio whenever the speed is not 1x. - Live streaming cannot switch to an
@60/@120resolution — disabled in both native SDKs.videoResolutionHFR options affect recording only. speedRatioaccepts only1,0.5,0.25,0.125; any other value throwsArgumentError. Omitting it is equivalent to1.0.
LibraryCore - Event Library
final libraryCore = LibraryCore.getInstance();
// Query event list
libraryCore?.getEventRecordByFilter(filterEntry,
onSuccess: (code, msg, eventData) => print('Event count: ${eventData.list?.length}'),
onError: (code, msg) => print('Query failed: $msg'),
);
// Query event details
libraryCore?.getEventDetail(false, 'video_event_key',
onSuccess: (code, msg, detail) {},
onError: (code, msg) {},
);
// Download event resources (add `speedRatio:` to export a slow-motion copy)
libraryCore?.downloadSource(tasks, false,
onProgress: (downloadIndex, total, progress) =>
print('Downloading $downloadIndex/$total: $progress'),
onFinish: (result, sharePathList) =>
print('Download ${result ? 'complete' : 'failed'}: $sharePathList'),
);
// Mark as read / bookmark
libraryCore?.setReadStatus(1, 'traceId', onSuccess: ..., onError: ...);
libraryCore?.setMarkStatus(1, 'traceId', onSuccess: ..., onError: ...);
BirdRecognizeCore - Bird Recognition
BirdRecognizeCore.getInstance()?.getWikiCurrentBirdInfo(birdModel,
onSuccess: (code, msg, bird) => print('Bird: ${bird.name}'),
onError: (code, msg) => print('Query failed: $msg'),
);
Project Structure
lib/
├── smart_device_core.dart # SDK entry point
├── bind_core.dart # Device binding module
├── bird_recognize_core.dart # Bird recognition module
├── device_manage_core.dart # Device management module
├── device_setting_core.dart # Device settings module
├── device_sleep_plan_core.dart # Sleep schedule module
├── library_core.dart # Event library module
├── common/ # Base communication layer
│ ├── sdk.dart
│ ├── sdk_method_channel.dart
│ ├── sdk_platform_interface.dart
│ └── callback_queue.dart
├── models/ # Data models
│ ├── bird/
│ ├── device/
│ ├── library/
│ └── location/
├── video/ # Video playback module
│ ├── video_player.dart # Player abstract interface
│ ├── webrtc_player.dart # WebRTC player
│ ├── ijk_player.dart # IJK player
│ └── live_manager_instance.dart
└── view/
└── surface_view.dart # Native rendering view
Running the Example
cd example
flutter pub get
flutter run
The example defaults to the vicoo tenant on production. Override the tenant and environment with --dart-define:
flutter run --dart-define=TENANT_ID=kiwibit --dart-define=SDK_DEBUG=true --dart-define=AUTH_BASE_URL=https://api-staging-us.vicohome.io
Changelog
See CHANGELOG.md.
Libraries
- bind_core
- bird_recognize_core
- common/callback_queue
- common/sdk
- common/sdk_method_channel
- common/sdk_platform_interface
- device_manage_core
- device_ota_core
- device_setting_core
- device_sleep_plan_core
- library_core
- models/bind_device_model
- userSn : "AIC9L8LPYPM0060" serialNumber : "bb4298cfec13e09704e13a06acaae4a8" modelNo : "CG1" apInfo : "xxxx" icon : "https://addx-device-config.s3.amazonaws.com/battery/2021/1632404008_G2%E5%A4%87%E4%BB%BD%203%403x.png%22" smallIcon : "https://addx-device-config.s3.amazonaws.com/battery/2021/1632404008_G2%E5%A4%87%E4%BB%BD%203%403x.png%22" apRuleTextDeviceStatePosition : "19-21" displayModelNo : "" wiredMacAddress : "" macAddress : "11.111.11.11" supportApConnect : 1 supportApSetWifi : 1 net : 1
- models/bird/bird_model_bean
- models/callback
- models/device/device_attributes_bean
- models/device/device_bean
- models/device/device_data_bean
- models/discover_callback
- models/GlobalCallback
- models/library/library_event_bean
- models/library/library_event_detail_bean
- models/library/library_filter_bean
- models/library/library_status_bean
- models/library/library_tag_bean
- models/library/library_zone_bean
- models/library_download_callback
- models/location/pre_location_bean
- models/nature_chat
- models/ota_bean
- models/ota_callback
- models/pre_location_bean
- models/sdk_success_response
- models/smart_device_core
- models/start_bind_callback
- models/wifi_info
- nature_chat_core
- smart_device_core
- video/custom_param
- video/ijk_player
- video/ilive_state_listener
- video/live_manager_instance
- video/LiveCallback
- video/model/have_record_day_response
- video/model/peer_connection_state
- video/model/playback_speed
- video/model/video_resolution
- video/model/video_time_model_response
- video/video_call_back
- video/video_player
- video/webrtc_player
- view/surface_view