Device Management

Last Updated on : 2024-01-30 03:37:16download

This topic describes the device management services, including device information and device schedule.

Device information

For more information, see Device Information. This section describes how to display device information.

Define data model

class CellModel: NSObject {
    var title: String
    var detail: String

    init(title: String, detail: String) {
        self.title = title
        self.detail = detail
    }
}

This model is used for displaying lists. The UI looks like this:

Device Management

Create a controller

class DeviceDetailKitInfoVC: UITableViewController {

    var items: [CellModel] = []
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        self.tableView.reloadData()
    }
}

extension DeviceDetailKitInfoVC {
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .value1, reuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        cell.textLabel?.text = self.items[indexPath.row].title
        cell.detailTextLabel?.text = self.items[indexPath.row].detail
        return cell
    }
}

Create a controller to display device information. items stores the data, which will be present on the UI.

Get data

  1. The device ID is required to request device information. Therefore, pass in the device ID. Alter the code:

    class DeviceDetailKitInfoVC: UITableViewController {
        var deviceId: String
    
        init(deviceId: String) {
            self.deviceId = deviceId
            super.init(nibName: nil, bundle: nil)
        }
    }
    
    
  2. To get device information through ThingDeviceInfoManager, create a ThingDeviceInfoManager object. Alter the code:

    class DeviceDetailKitInfoVC: UITableViewController {
        var manager: ThingDeviceInfoManager
    
        init(deviceId: String) {
            self.deviceId = deviceId
            self.manager = ThingDeviceInfoManager(deviceId: deviceId)
            super.init(nibName: nil, bundle: nil)
        }
    }
    
  3. With the ThingDeviceInfoManager object, you can request the data.

    class DeviceDetailKitInfoVC: UITableViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
            self.loadData()
        }
    
        func loadData() {
            SVProgressHUD.show()
            self.manager.fetchDataSuccess { [weak self] info, hardware in
                var list = [CellModel]()
                list.append(CellModel(title: "devId", detail: info.devId))
                list.append(CellModel(title: "iccid", detail: info.iccid ?? ""))
                list.append(CellModel(title: "netStrength", detail: info.netStrength ?? ""))
                list.append(CellModel(title: "lanIp", detail: info.lanIp ?? ""))
                list.append(CellModel(title: "ip", detail: info.ip ?? ""))
                list.append(CellModel(title: "mac", detail: info.mac ?? ""))
                list.append(CellModel(title: "timezone", detail: info.timezone ?? ""))
                list.append(CellModel(title: "channel", detail: info.channel ?? ""))
                list.append(CellModel(title: "rsrp", detail: info.rsrp != nil ? "\(info.rsrp!)" : ""))
                list.append(CellModel(title: "wifiSignal", detail: info.wifiSignal != nil ? "\(info.wifiSignal!)" : ""))
                list.append(CellModel(title: "homekitCode", detail: info.homekitCode ?? ""))
                list.append(CellModel(title: "connectAbility", detail: "\(info.connectAbility)"))
                list.append(CellModel(title: "vendorName", detail: info.vendorName ?? ""))
                self?.items = list
                self?.tableView.reloadData()
                SVProgressHUD.dismiss()
            } failure: { e in
                SVProgressHUD.dismiss()
            }
        }
    }
    
    1. Define the method loadData.
    2. In this method, data is obtained through ThingDeviceInfoManager.fetchDataSuccess:failure:, items is constructed accordingly, and the UI is then refreshed.
    3. Finally, call loadData in the viewDidLoad method.

    The UI looks like this:

    Device Management

Listen for signal changes

The device’s signal value is reported via MQTT. Therefore, register a listener for signals to respond to changes in the device signals.

class DeviceDetailKitInfoVC: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        self.manager.add(self)
        self.loadData()
    }

}

extension DeviceDetailKitInfoVC: ThingDeviceInfoManagerListener {
    func deviceInfoManager(_ manager: ThingDeviceInfoManager, wifiSignalDidUpdate wifiSignal: Int32) {
        let item = self.items.first { item in
            return item.title == "wifiSignal"
        }
        item?.detail = "\(wifiSignal)"
        self.tableView.reloadData()
    }
}

Register the listener in viewDidLoad and then implement ThingDeviceInfoManagerListener. This enables you to receive notifications of signal changes and update the UI accordingly.

Complete code

class DeviceDetailKitInfoVC: UITableViewController {

    var items: [CellModel] = []
    var deviceId: String

    var manager: ThingDeviceInfoManager

    init(deviceId: String) {
        self.deviceId = deviceId
        self.manager = ThingDeviceInfoManager(deviceId: deviceId)
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        self.manager.add(self)
        self.loadData()
    }

    func loadData() {
        SVProgressHUD.show()
        self.manager.fetchDataSuccess { [weak self] info, hardware in
            var list = [CellModel]()
            list.append(CellModel(title: "devId", detail: info.devId))
            list.append(CellModel(title: "iccid", detail: info.iccid ?? ""))
            list.append(CellModel(title: "netStrength", detail: info.netStrength ?? ""))
            list.append(CellModel(title: "lanIp", detail: info.lanIp ?? ""))
            list.append(CellModel(title: "ip", detail: info.ip ?? ""))
            list.append(CellModel(title: "mac", detail: info.mac ?? ""))
            list.append(CellModel(title: "timezone", detail: info.timezone ?? ""))
            list.append(CellModel(title: "channel", detail: info.channel ?? ""))
            list.append(CellModel(title: "rsrp", detail: info.rsrp != nil ? "\(info.rsrp!)" : ""))
            list.append(CellModel(title: "wifiSignal", detail: info.wifiSignal != nil ? "\(info.wifiSignal!)" : ""))
            list.append(CellModel(title: "homekitCode", detail: info.homekitCode ?? ""))
            list.append(CellModel(title: "connectAbility", detail: "\(info.connectAbility)"))
            list.append(CellModel(title: "vendorName", detail: info.vendorName ?? ""))
            self?.items = list
            self?.tableView.reloadData()
            SVProgressHUD.dismiss()
        } failure: { e in
            SVProgressHUD.dismiss()
        }

    }
}

extension DeviceDetailKitInfoVC {
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .value1, reuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        cell.textLabel?.text = self.items[indexPath.row].title
        cell.detailTextLabel?.text = self.items[indexPath.row].detail
        return cell
    }
}

extension DeviceDetailKitInfoVC: ThingDeviceInfoManagerListener {
    func deviceInfoManager(_ manager: ThingDeviceInfoManager, wifiSignalDidUpdate wifiSignal: Int32) {
        let item = self.items.first { item in
            return item.title == "wifiSignal"
        }
        item?.detail = "\(wifiSignal)"
        self.tableView.reloadData()
    }
}

Device schedule

For more information, see Device Schedule. This section describes how to display device schedule.

Create a controller

Create a new controller to display the schedule list of devices or groups and handle the cell tap event.

class DeviceDetailKitTimerVC: UITableViewController {

    var items: [ThingTimerModel] = []

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        self.tableView.reloadData()
    }

    func handle(timer: ThingTimerModel) {
        // Process the tap event.
    }
}

extension DeviceDetailKitTimerVC {
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .value1, reuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        cell.textLabel?.text = self.items[indexPath.row].time
        cell.detailTextLabel?.text = self.items[indexPath.row].status ? "on" : "off"
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        self.handle(timer: self.items[indexPath.row])
    }
}

Get schedule data

  1. Determine the source of the schedule, whether it is a device or a group, and pass in the corresponding device or group ID.

    class DeviceDetailKitTimerVC: UITableViewController {
    
        var bizId: String // Device ID or group ID
        var isGroup: Bool // Indicates whether this is a group.
    
        init(bizId: String, isGroup: Bool) {
            self.bizId = bizId
            self.isGroup = isGroup
            super.init(nibName: nil, bundle: nil)
        }
    }
    
  2. The operation of the group relies on ThingDeviceTimerManager, so instantiate a ThingDeviceTimerManager object.

    class DeviceDetailKitTimerVC: UITableViewController {
    
        var bizId: String
        var isGroup: Bool
        var manager: ThingDeviceTimerManager
    
        var items: [ThingTimerModel] = []
    
        init(bizId: String, isGroup: Bool) {
            self.bizId = bizId
            self.isGroup = isGroup
            self.manager = ThingDeviceTimerManager()
            super.init(nibName: nil, bundle: nil)
        }
    }
    
  3. Retrieve data.

    class DeviceDetailKitTimerVC: UITableViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
            self.loadData()
        }
    
        func loadData() {
            SVProgressHUD.show()
            self.getTimerList { [weak self] list in
                self?.items = list
                self?.tableView.reloadData()
                SVProgressHUD.dismiss()
    
                guard let self = self, self.isGroup == false && self.manager.isDeviceCanSync(bizId) else {return}
                manager.syncTimers(list, toDevice: bizId) {} failure: { _ in }
    
            } failure: { e in
                SVProgressHUD.dismiss()
            }
        }
    
        func getTimerList(success: @escaping ([ThingTimerModel]) -> Void, failure: @escaping (Error) -> Void) {
            let params = ThingDeviceTimerGetParams(bizType: isGroup ? .group : .device, bizId: bizId, category: "")
            self.manager.getTimers(params, success: success, failure: failure)
        }
    }
    
    • For the purpose of reuse, define getTimerList(success:failure:). Internally, ThingDeviceTimerManager.getTimers(_:success:failure) is called.
    • Define loadData, which will be called during viewDidLoad. Retrieve the schedule list using the getTimerList(success:failure:) method.
    • The loadData method saves data, refreshes the UI, as well as synchronizes the schedule data with the device through ThingDeviceTimerManager.syncTimers(_:toDevice:success:failure) when applicable.

    So far, the list of device schedules can be displayed properly.

Add a schedule

Add a button for adding schedules to the device or group.

class DeviceDetailKitTimerVC: UITableViewController {

    func setUpNavigationItem() {
        let title = "Add"
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: title, style: .plain, target: self, action: #selector(add))
    }

    @objc func add() {
        SVProgressHUD.show()

        var dps: [AnyHashable: Any] = ["1": true]
        let params = ThingDeviceTimerAddParams(bizType: isGroup ? .group : .device, bizId: bizId, category: "", loops: "0000000", time: "12:30", dps: dps, aliasName: "New Schedule", isAppPush: true, status: true)
        self.manager.addTimer(params) { [weak self] timerId in
            self?.getTimerList(success: { list in
                self?.items = list
                self?.tableView.reloadData()
                SVProgressHUD.dismiss()
            }, failure: { e in
                SVProgressHUD.dismiss()
            })
        } failure: { e in
            SVProgressHUD.dismiss()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "DeviceDetailListViewControllerReuseIdentifier")
        self.setUpNavigationItem()
        self.loadData()
    }
}
  1. Create an Add button to the navigation bar.

  2. After the button is tapped, call ThingDeviceTimerManager.addTimer(_:success:failure:) to add a schedule.

  3. After a schedule is added, refresh the schedule list using getTimerList(success:failure:).

    Construct the parameters for ThingDeviceTimerAddParams based on your needs.

Update a schedule

class DeviceDetailKitTimerVC: UITableViewController {
    func handle(timer: ThingTimerModel) {
        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        alert.addAction(UIAlertAction(title: "Update", style: .default, handler: { action in
            self.update(timer: timer)
        }))

        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        self.present(alert, animated: true)
    }

    func update(timer: ThingTimerModel) {
        let params = ThingDeviceTimerUpdateParams(timerId: timer.timerId, bizType: self.isGroup ? .group : .device, bizId: self.bizId, loops: timer.loops, time: timer.time, dps: timer.dps, aliasName: timer.aliasName, isAppPush: !timer.isAppPush, status: !timer.status)

        SVProgressHUD.show()

        self.manager.updateTimer(params) { [weak self] in
            self?.getTimerList { list in
                self?.items = list
                self?.tableView.reloadData()
                SVProgressHUD.dismiss()
            } failure: { e in
                SVProgressHUD.dismiss()
            }
        } failure: { e in
            SVProgressHUD.dismiss()
        }
    }
}

Implement the method for cell tap events.

  1. Add an update action using an actionSheet.

  2. After the button is tapped, navigate to update(timer:), which invokes ThingDeviceTimerManager.updateTimer(_:success:failure:) to update the schedule.

  3. After the schedule is updated, refresh the schedule list using getTimerList(success:failure:).

    Construct the parameters for ThingDeviceTimerUpdateParams based on your needs.

Update schedule status

class DeviceDetailKitTimerVC: UITableViewController {
    func handle(timer: ThingTimerModel) {
        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        alert.addAction(UIAlertAction(title: "Update", style: .default, handler: { action in
            self.update(timer: timer)
        }))

        alert.addAction(UIAlertAction(title: "Update Status", style: .default, handler: { action in
            self.updateStatus(timer: timer)
        }))

        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        self.present(alert, animated: true)
    }

    func updateStatus(timer: ThingTimerModel) {
        let params = ThingDeviceTimerStatusUpdateParams(timerId: timer.timerId, bizType: self.isGroup ? .group : .device, bizId: self.bizId, loops: timer.loops, time: timer.time, dps: timer.dps, aliasName: timer.aliasName, isAppPush: timer.isAppPush, status: !timer.status)

        SVProgressHUD.show()

        self.manager.updateTimerStatus(params) { [weak self] in
            self?.getTimerList { list in
                self?.items = list
                self?.tableView.reloadData()
                SVProgressHUD.dismiss()
            } failure: { e in
                SVProgressHUD.dismiss()
            }
        } failure: { e in
            SVProgressHUD.dismiss()
        }
    }
}
  1. Add a status update action.

  2. After the button is tapped, navigate to updateStatus(timer:), which invokes ThingDeviceTimerManager.updateTimerStatus(_:success:failure:) to update the schedule status.

  3. After the schedule is updated, refresh the schedule list using getTimerList(success:failure:).

    Construct the parameters for ThingDeviceTimerStatusUpdateParams based on your needs.

Delete a schedule

class DeviceDetailKitTimerVC: UITableViewController {
    func handle(timer: ThingTimerModel) {
        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        alert.addAction(UIAlertAction(title: "Update", style: .default, handler: { action in
            self.update(timer: timer)
        }))

        alert.addAction(UIAlertAction(title: "Update Status", style: .default, handler: { action in
            self.updateStatus(timer: timer)
        }))

        alert.addAction(UIAlertAction(title: "Delete", style: .default, handler: { action in
            self.delete(timer: timer)
        }))

        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        self.present(alert, animated: true)
    }

    func delete(timer: ThingTimerModel) {
        let params = ThingDeviceTimerRemoveParams(timerId: timer.timerId, bizType: self.isGroup ? .group : .device, bizId: self.bizId)

        SVProgressHUD.show()

        self.manager.removeTimer(params) { [weak self] in
            self?.getTimerList { list in
                self?.items = list
                self?.tableView.reloadData()
                SVProgressHUD.dismiss()
            } failure: { e in
                SVProgressHUD.dismiss()
            }
        } failure: { e in
            SVProgressHUD.dismiss()
        }
    }
}
  1. Add a delete action.

  2. After the button is tapped, navigate to updateStatus(timer:), which invokes ThingDeviceTimerManager.updateTimerStatus(_:success:failure:) to delete the schedule.

  3. After the schedule is deleted, refresh the schedule list using getTimerList(success:failure:).

    Construct the parameters for ThingDeviceTimerRemoveParams based on your needs.