Last Updated on : 2024-07-16 06:28:45download
Device Details UI BizBundle supports the following features:
Add the components of the Device Details UI BizBundle to Podfile
and run the command pod update
.
source "https://github.com/tuya/tuya-pod-specs"
source 'https://cdn.cocoapods.org/'
target 'your_target_name' do
# Adds the Device Details UI BizBundle.
pod 'ThingSmartDeviceDetailBizBundle'
# Imports Bluetooth components, if you need Bluetooth features
# pod 'ThingBluetoothInterface'
# pod 'ThingBLEMeshInterfaceImpl'
end
The UI BizBundle supports the upload of device icons. To implement this feature, the permissions on the system album and camera must be granted. This requires specific declarations of privacy and permissions from Apple.
Add the following permission declaration to info.plist
of your project:
<!-- Album -->
<key>NSPhotoLibraryUsageDescription</key>
<string>Authorizes the app to access the album of the mobile phone</string>
<!-- Camera -->
<key>NSCameraUsageDescription</key>
<string>Authorizes the app to access the camera of the mobile phone</string>
If a Bluetooth device is connected, or you use services that rely on Bluetooth capabilities such as creating groups or removing devices, you need to add the following permission declaration to info.plist
of your project:
<!-- Bluetooth -->
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This allows the app to find and connect to Bluetooth accessories. This app can also locate Bluetooth devices by using Bluetooth. </string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>If you want to add or use a Bluetooth device, please turn on the Bluetooth feature of the mobile phone. </string>
Create the configuration file deviceDetailConfig.json
in the main project. If the file already exists, skip the creation.
Add the following content to deviceDetailConfig.json
:
[
{
"name": "headerSection",
"items": [
{
"cellType": "header"
},{
"cellType": "device_info"
},{
"cellType": "net_setting"
},{
"cellType":"group_edit_devices"
},{
"cellType":"scene_and_automation"
}
]
},{
"name": "offLineWarnSection",
"header": {
"cellType":"section_off_line_warn"
},
"items": [
{
"cellType" : "off_line_warn"
}
]
},{
"name": "otherSection",
"header": {
"cellType":"section_other"
},
"items": [
{
"cellType":"bind_multi_control_link"
},
{
"cellType":"group_create"
},
{
"cellType":"help_and_feedback"
},
{
"cellType":"add_icon_to_home_screen"
},
{
"cellType":"show_infrared_gateway_sub_device"
},
{
"cellType":"check_device_network"
},
{
"cellType":"check_firmware_update"
}
]
},{
"name": "footerSection",
"items": [
{
"cellType":"footer"
}
],
"margin": {
"top": 16
}
}
]
Customize device details.
The sequence of the item
parameter in the deviceDetail
array determines the sequence in which each item
is displayed on the device details page. If the item
is removed, the associated device feature will also be removed from the device details page.
Item of deviceDetail |
Device feature |
---|---|
header | View and modify the device icon, device name, and location. |
device_info | The device information. |
net_setting | Display backup Wi-Fi networks. |
off_line_warn | Notify users of devices getting offline. |
section_other | This is a section header and serves no purpose. |
bind_multi_control_link | Enable multi-control linkage. Multi-Control Linkage UI BizBundle must be additionally integrated. |
scene_and_automation | Tap-to-run and automation, requiring integration with the Scene UI BizBundle. |
group_edit_devices | Edit groups, requiring integration with the Group Management UI BizBundle. |
group_create | Create groups, requiring integration with the Group Management UI BizBundle. |
help_and_feedback | Provide FAQ and feedback. FAQ UI BizBundle must be additionally integrated. |
check_firmware_update | Check for firmware updates. OTA UI BizBundle must be additionally integrated. |
add_icon_to_home_screen | Add shortcuts to the home screen. |
show_infrared_gateway_sub_device | Show remote controls. |
footer | Remove a device. |
ThingSmartHomeDataProtocol
is deprecated and ThingFamilyProtocol
is recommended.
/**
To use this API method to get the current home data, you must use 'updateCurrentHomeId:' API of the protocol when the current home ID is updated.
Returns the current home. If the current user does not have a home, nil is returned.
@return ThingSmartHome
*/
- (ThingSmartHome *)getCurrentHome;
Objective-C:
#import <ThingSmartBizCore/ThingSmartBizCore.h>
#import <ThingModuleServices/ThingSmartHomeDataProtocol.h>
- (void)initCurrentHome {
// Registers the protocol to be implemented.
[[ThingSmartBizCore sharedInstance] registerService:@protocol(ThingSmartHomeDataProtocol) withInstance:self];
}
// Implements the protocol method.
- (ThingSmartHome *)getCurrentHome {
ThingSmartHome *home = [ThingSmartHome homeWithHomeId:@"Current home ID"];
return home;
}
Swift:
import ThingSmartDeviceKit
class ThingMessageCenterTest: NSObject,ThingSmartHomeDataProtocol{
func test() {
ThingSmartBizCore.sharedInstance().registerService(ThingSmartHomeDataProtocol.self, withInstance: self)
}
func getCurrentHome() -> ThingSmartHome! {
let home = ThingSmartHome.init(homeId: 111)
return home
}
}
Check for firmware updates. OTA UI BizBundle must be additionally integrated.
Provide FAQ and feedback. FAQ UI BizBundle must be additionally integrated.
Manage group devices. Group Management UI BizBundle must be additionally integrated.
Enable multi-control linkage. Multi-Control Linkage UI BizBundle must be additionally integrated.
Tap-to-run and automation. Scene UI BizBundle must be additionally integrated.
Bluetooth feature. After you add relevant dependencies and declarations in Podfile and Info.plist
, you can call the Bluetooth start method before using it.
#import <ThingBluetoothInterface/ThingBluetoothInterface.h>
[TheBLEInterfaceService startScan];
Method | Parameter |
---|---|
Navigate to the network detection page | The device ID. |
Navigate to device details by means of push | ThingSmartDeviceModel or ThingSmartGroupModel . |
Check whether to display infrared sub-devices | devId and spaceId . |
Check whether displaying infrared sub-devices is enabled. | devId and spaceId . |
Display the notification of infrared sub-device status changes | / |
/// Navigates to the page of network detection.
/// @param devId The device ID.
- (void)gotoDeviceDetailNetworkViewControllerWithDeviceId:(NSString *)devId;
/// Navigates to device details by means of push.
/// @param device The device.
/// @param group The group if any. It is optional.
- (void)gotoDeviceDetailDetailViewControllerWithDevice:(ThingSmartDeviceModel *)device group:(ThingSmartGroupModel *)group;
@optional
/// Checks whether to display infrared sub-devices.
/// @param devId The device ID. If a non-infrared gateway or sub-device is passed in, YES is returned.
/// @param spaceId The space ID.
/// @return The return value. Valid values: YES: display.
NO: not display.
- (BOOL)getInfraredDisplayStatusWithDevId:(nullable NSString *)devId spaceId:(long long)spaceId;
@optional
/// Checks whether displaying infrared sub-devices is enabled.
/// @param devId The device ID.
/// @param spaceId The space ID.
/// @return The return value. Valid values: YES: display.
NO: not display.
- (BOOL)cacheOfInfraredDisplayStatusWithDevId:(nullable NSString *)devId spaceId:(long long)spaceId;
@optional
/// Displays the notification of infrared sub-device status changes.
- (nullable NSNotificationName)subDeviceDisplayStatusChangeNotificationName;
Objective-C:
#import <ThingSmartBizCore/ThingSmartBizCore.h>
#import <ThingModuleServices/ThingDeviceDetailProtocol.h>
id<ThingDeviceDetailProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingDeviceDetailProtocol)];
// Navigates to the page of network detection.
[impl gotoDeviceDetailNetworkViewControllerWithDeviceId:@"Device ID"];
// Navigates to device details by means of push.
// For a device, 'new ThingSmartDevice' is called.
ThingSmartDevice * device = [ThingSmartDevice deviceWithDeviceId:@"Device ID"]
[impl gotoDeviceDetailDetailViewControllerWithDevice: device.deviceModel group: nil];
// For a group, 'new ThingSmartGroup' is called.
ThingSmartGroup * group = [ThingSmartDevice groupWithGroupId:@"Group ID"]
[impl gotoDeviceDetailDetailViewControllerWithDevice: nil group: group.deviceModel];
Swift:
let impl = ThingSmartBizCore.sharedInstance().service(of: ThingDeviceDetailProtocol.self) as?ThingDeviceDetailProtocol
// Navigates to the page of network detection.
impl?.gotoDeviceDetailNetworkViewController(withDeviceId: "Device ID")
// Navigates to device details by means of push.
// For a device, 'new ThingSmartDevice' is called.
let device = ThingSmartDevice.init(deviceId: "vdevo160888044089994")
impl?.gotoDeviceDetailDetailViewController(withDevice: device?.deviceModel, group: nil)
// For a group, 'new ThingSmartGroup' is called.
let group = ThingSmartGroup.init(groupId: "Group ID")
impl?.gotoDeviceDetailDetailViewController(withDevice: nil, group: group?.groupModel)
Add to Home Screen: This feature allows users to create a bookmark on the home screen. This bookmark works as a shortcut to a device panel. After users tap this bookmark, your app is evoked and users are navigated to the target device panel. To enable this feature, perform the following steps:
Add add_icon_to_home_screen
to deviceDetailConfig.json
. Otherwise, this feature is unavailable.
Set appScheme
in the file thing_custom_config.json
. In the following example, you need to replace the default value Your appScheme with another value.
{
"config": {
...
"appScheme": "Your appScheme"
},
...
}
Add the value of appScheme
in the file thing_custom_config.json
to URL Scheme
. In the preceding example, this default value is Your appScheme
. It must be replaced with another value.
Process routing events in AppDelegate
:
Objective-C:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
if ([[url.scheme lowercaseString] isEqualToString:@"oralcaretest"]) {
NSDictionary *params = [self dictionaryFromQuery:url.query usingEncoding:NSUTF8StringEncoding];
NSString *host = url.host;
if ([host isEqualToString:@"panelEx"]) {
id <ThingPanelProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingPanelProtocol)];
ThingSmartDevice *device = [ThingSmartDevice deviceWithDeviceId:params[@"devId"]?: @""];
[impl getPanelViewControllerWithDeviceModel:device.deviceModel initialProps:nil contextProps:nil completionHandler:^(__kindof UIViewController * _Nullable panelViewController, NSError * _Nullable error) {
if (error) {
NSLog(@"Load error: %@", error);
}
}];
}
return YES;
}
return NO;
}
- (NSDictionary *)dictionaryFromQuery:(NSString *)query usingEncoding:(NSStringEncoding)encoding {
if (!([query isKindOfClass:[NSString class]] && query.length > 0)) {
return nil;
}
NSCharacterSet *delimiterSet = [NSCharacterSet characterSetWithCharactersInString:@"&;"];
NSMutableDictionary* pairs = [NSMutableDictionary dictionary];
NSScanner* scanner = [[NSScanner alloc] initWithString:query];
while (![scanner isAtEnd]) {
NSString* pairString = nil;
[scanner scanUpToCharactersFromSet:delimiterSet intoString:&pairString];
[scanner scanCharactersFromSet:delimiterSet intoString:NULL];
NSArray* kvPair = [pairString componentsSeparatedByString:@"="];
if (kvPair.count == 2) {
NSString* key = [[kvPair objectAtIndex:0]
stringByReplacingPercentEscapesUsingEncoding:encoding];
NSString* value = [[kvPair objectAtIndex:1]
stringByReplacingPercentEscapesUsingEncoding:encoding];
[pairs setObject:value forKey:key];
}
}
return [NSDictionary dictionaryWithDictionary:pairs];
}
Swift:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if let scheme = url.scheme, scheme.lowercased() == "oralcaretest" {
let params = self.params(from: url.query, .utf8)
if let host = url.host, host == "panelEx", let devId = params?["devId"] as? String, let device = ThingSmartDevice(deviceId: devId) {
let impl: ThingPanelProtocol? = ThingSmartBizCore.sharedInstance().service(of: ThingPanelProtocol.self) as? ThingPanelProtocol
impl?.getPanelViewController(with: device.deviceModel, initialProps: nil, contextProps: nil, completionHandler: { vc, error in
if error != nil {
print(error!.localizedDescription)
}else{
print("push the vc")
}
})
}
return true
}
return false
}
func params(from query: String?, _ encoding: String.Encoding) -> Dictionary<String, Any>? {
guard let queryString = query, queryString.count > 0 else {
return nil
}
let set = CharacterSet(charactersIn: "&;")
var pairs = Dictionary<String, Any>()
let scanner = Scanner(string: queryString)
while !scanner.isAtEnd {
var pairString: NSString? = ""
scanner.scanUpToCharacters(from: set, into: &pairString)
scanner.scanCharacters(from: set, into: nil)
if let kvPair = pairString?.components(separatedBy: "="), kvPair.count == 2 {
let key: String = kvPair.first!.removingPercentEncoding!
let value: String = kvPair.last!
pairs[key] = value
}
}
return pairs
}
By default, the SDK does not show the feature that allows users to hide location data from device details. To show the feature, set is_support_home_manager
to true in thing_custom_config.json
.
{
"config": {
...
"is_support_home_manager": true,
},
...
}
Customize ThingDeviceDetailExternalProtocol
.
/// @brief Customizes which page to return to after a device is removed.
/// @return The return value. Valid values: YES: custom. NO: default logic.
- (BOOL)customExitWhenDeleted;
Specific features can be implemented with the configuration file deviceDetailConfig.json
. You can add the custom parameter type
to deviceDetail
in deviceDetailConfig.json
.
The value of type
must start with c_
. For example, c_test_insert
and c_test_async_insert
can be added.
[
{
"name": "headerSection",
"items": [
{
"cellType": "header"
},{
"cellType": "device_info"
},{
"cellType": "net_setting"
},{
"cellType":"group_edit_devices"
}
]
},{
"name": "offLineWarnSection",
"header": {
"cellType":"section_off_line_warn"
},
"items": [
{
"cellType" : "off_line_warn"
}
]
},{
"name": "otherSection",
"header": {
"cellType":"section_other"
},
"items": [
{
"cellType":"bind_multi_control_link"
},
{
"cellType":"group_create"
},
{
"cellType":"help_and_feedback"
},
{
"cellType":"add_icon_to_home_screen"
},
{
"cellType":"show_infrared_gateway_sub_device"
},
{
"cellType":"check_device_network"
},
{
"cellType":"check_firmware_update"
},
{
"cellType":"c_test_insert"
},
{
"cellType":"c_test_async_insert"
}
]
},{
"name": "footerSection",
"items": [
{
"cellType":"footer"
}
],
"margin": {
"top": 16
}
}
]
API description: clear the data
Clears data before the custom item
is inserted.
/// Clears the custom item.
- (void)clearInsertItem;
API description: Return item data synchronously
/// Implements the synchronous callback.
insertDevMenuItemBlock returns the callback when device details are refreshed. type is equivalent to cellType in the configuration file.
-(void)insertDevMenuItem:(InsertDevMenuItemBlock) insertDevMenuItemBlock customType:(NSString *)type;
//@param type The custom type specified in configList.json.
//@param device The device model.
//@param group The group model. If the value of the group is nil, device data is returned. Otherwise, group data is returned.
//@return The object that follows the protocol ThingDeviceDetailCustomMenuModel. If nil is returned, this type of item is not displayed.
typedef id<ThingDeviceDetailCustomMenuModel> _Nullable (^InsertDevMenuItemBlock)(NSString* _Nonnull type,
ThingSmartDeviceModel* _Nullable device,
ThingSmartGroupModel* _Nullable group);
API description: Return item data asynchronously
/// Implements the asynchronous callback. insertDevMenuItemAsyncBlock returns the callback when device details are refreshed. type is equivalent to cellType in the configuration file.
-(void)insertDevMenuItemAsync:(InsertDevMenuItemAsyncBlock) insertDevMenuItemAsyncBlock customType:(NSString *)type;
// Inserts the asynchronous operation to process the item. At the end of the operation, call complete(id<ThingDeviceDetailCustomMenuMode>). The result data is returned to the device details page and the list is refreshed.
typedef void (^InsertDevMenuItemAsyncBlock)(NSString* _Nonnull type,
ThingSmartDeviceModel* _Nullable device,
ThingSmartGroupModel* _Nullable group,
InsertDevMenuItemComplete _Nonnull complete);
First, create a Model class that follows the protocol ThingDeviceDetailCustomMenuModel
.
Objective-C:
// Customizes a class that adopts the protocol ThingDeviceDetailCustomMenuModel.
@interface CustomMenuModel : NSObject<ThingDeviceDetailCustomMenuModel>
/// The title.
@property (nonatomic,copy) NSString *title;
/// The subtitle.
@property (nonatomic,copy) NSString *detail;
@end
@implementation CustomMenuModel
@end
Swift:
class CustomMenuModel: NSObject, ThingDeviceDetailCustomMenuModel{
var title : String?
var detail : String?
}
Then, configure the callback block
.
Objective-C:
id<ThingDeviceDetailProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingDeviceDetailProtocol)];
[impl clearInsertItem];// Clears data before the custom item is inserted.
[impl insertDevMenuItem:^ id<ThingDeviceDetailCustomMenuModel> (NSString * _Nonnull type, ThingSmartDeviceModel * _Nonnull device, ThingSmartGroupModel * _Nonnull group) {
if ([type isEqualToString:@"c_test_insert"]) {
CustomMenuModel *model = [CustomMenuModel new];
if (group) { // If the value of the group is nil, device data is returned. Otherwise, group data is returned.
model.title = type;
model.detail = @"group";
}else{
model.title = type;
model.detail = @"device";
}
return model;
}
return nil;
} customType:@"c_test_insert"];
[impl insertDevMenuItemAsync:^(NSString * _Nonnull type, ThingSmartDeviceModel * _Nonnull device, ThingSmartGroupModel * _Nonnull group, InsertDevMenuItemComplete _Nonnull complete) {
if ([type isEqualToString:@"c_test_async_insert"]) {
// The time-consuming operation.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CustomMenuModel *model = [CustomMenuModel new];
if (group) { // If the value of the group is nil, device data is returned. Otherwise, group data is returned.
model.title = type;
model.detail = @"group";
}else{
model.title = type;
model.detail = @"device";
}
complete(model);
});
}
} customType:@"c_test_async_insert"];
Swift:
let impl = ThingSmartBizCore.sharedInstance().service(of: ThingDeviceDetailProtocol.self) as?ThingDeviceDetailProtocol
impl?.clearInsertItem // Clears data before the custom item is inserted.
impl?.insertDevMenuItem({ (type, deviceModel, groupModel) -> ThingDeviceDetailCustomMenuModel?in
if type == "c_test_insert" {// If the value of the group is nil, device data is returned. Otherwise, group data is returned.
let model = CustomMenuModel.init()
if groupModel != nil {
model.title = type
model.detail = "group"
}else{
model.title = type
model.detail = "device"
}
return model;
}
return nil;
} , customType: "c_test_insert")
impl?.insertDevMenuItemAsync({ (type, deviceModel, groupModel, complete) in
if type == "c_test_async_insert" {
// The time-consuming operation.
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
let model = CustomMenuModel.init()
if groupModel != nil {
model.title = type
model.detail = "group"
}else{
model.title = type
model.detail = "device"
}
complete(model);
}
}
} , customType: "c_test_async_insert");
Objective-C:
id<ThingDeviceDetailProtocol> impl = [[ThingSmartBizCore sharedInstance] serviceOfProtocol:@protocol(ThingDeviceDetailProtocol)];
[impl clickMenuItem: ^(NSString * _Nonnull type, ThingSmartDeviceModel * _Nonnull device, ThingSmartGroupModel * _Nonnull group) {
NSLog(@"clickItem: type:%@",type);
}];
Swift:
let impl = ThingSmartBizCore.sharedInstance().service(of: ThingDeviceDetailProtocol.self) as? ThingDeviceDetailProtocol
impl?.clickMenuItem({ (type, deviceModel, groupModel) in
print("clickItem: type:"+type);
})
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback