# MinewSensorKit说明文档
本套SDK仅支持Minew公司出品的蓝牙传感器设备。通过SDK可以帮助开发者处理手机和传感器之间的一切工作,包括:扫描设备,广播数据、连接设备,向设备写入数据,从设备接收数据等。
目前SDK仅支持资产温度传感器的使用。
# 前期工作
整体框架:PT100SensorBleManager
为设备管理类,在APP运行时始终是单例。MST03Entity
是设备实例类,此套件会为每一个设备生成一个实例,在扫描和连接后都会使用,内部包含设备广播数据,在扫描期间该数据会随着设备不停广播而更新。
PT100SensorBleManager
:设备管理类,可以扫描周围的设备,并且可以连接它们,校验它们等;
PT100SensorEntity
:扫描时获取到的资产温度传感器设备实例,继承自BaseBleDeviceEntity
;
# 导入到工程
开发环境
sdk最低支持Android 5.0,对应API Level为18。在module的
build.gradle
中设置minSdkVersion
为21或21以上android { defaultConfig { applicationId "com.xxx.xxx" minSdkVersion 21 } }
1
2
3
4
5
6
7将 jar包添加到module的libs文件夹下,并在该
module
的build.gradle
中添加如下语句(直接添加依赖):implementation files('libs/base_ble_library.jar') implementation files('libs/minew_pt100.jar') api 'org.lucee:bcprov-jdk15on:1.52.0'
1
2
3或者右键该jar文件,选择
Add as Library
,添加到当前module。添加.so库文件,App目录下build.gradle添加如下配置
android { defaultConfig { ndk { abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64' } } sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14在
AndroidManifest.xml
需要以下权限,如果targetSdkVersion
大于23,则需要做权限管理以获取权限:<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" tools:node="replace" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" tools:node="replace" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/> <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- Required to maintain app compatibility. --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 使用
sdk分为扫描、连接和读写三个阶段。
# 扫描部分
# 开始扫描
Android6.0系统以上,进行BLE扫描时,需要先申请到蓝牙权限后并且打开定位开关才能进行。
开启蓝牙扫描需要首先打开蓝牙,如果未打开蓝牙就去扫描,APP会闪退。可通过BLETool.checkBluetooth(this)来判断蓝牙是否已经打开。如果没有打开,可以先打开蓝牙。
val mBleManager = PT100SensorBleManager.getInstance()
when (BLETool.checkBluetooth(this@Mst01Pt100ScanDevicesListActivity)) {
BluetoothState.BLE_NOT_SUPPORT -> {
Toast.makeText(this@Mst01Pt100ScanDevicesListActivity, "Not Support BLE", Toast.LENGTH_SHORT).show()
}
BluetoothState.BLUETOOTH_OFF -> {
val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
launcherActivityResultForBle.launch(enableIntent)
}
BluetoothState.BLUETOOTH_ON -> {
manager.startScan(ModuleMst01Pt100Application.getApplication().mApplication, 5*60*1000,object : OnScanDevicesResultListener<PT100SensorEntity> {
override fun onScanResult(scanList: MutableList<PT100SensorEntity>?) {
}
override fun onStopScan(scanList: MutableList<PT100SensorEntity>?) {
}
})
}
else -> {
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
sdk内部并没有对蓝牙扫描时长进行处理,但是扫描是耗电操作,SDK默认5分钟就停止扫描了,如果还需要继续扫描,可以提供定时器或者刷新等操作以便继续调用扫描方法继续扫描设备。
# 取出数据
在扫描期间,APP能够通过sdk获取到设备当前的一部分数据。如下所示通过PT100SensorEntity
获取设备温度传感器数据,该数据保存在广播帧对象中。
sdk提供了BaseBleDeviceEntity
作为PT100SensorEntity
的基类,用于存储传感器设备的公有数据,如下表所示:
名称 | 类型 | 说明 |
---|---|---|
macAddress | String | 设备mac |
name | String | 设备名称 |
rssi | int | 信号强度 |
BaseBleDeviceEntity
还保存了一个Map,内部用于存储其在扫描期间获取到的设备广播数据帧,可通过如下方式取出:
val module:PT100SensorEntity
val industrialHtFrame : IndustrialHtFrame? = module.getMinewFrame(FrameType.INDUSTRIAL_TEMPERATURE_HUMIDITY_TAG_STATUS_V2_FRAME)?.let {
it as IndustrialHtFrame
}
val deviceStaticInfoFrame : DeviceStaticInfoFrame? = module.getMinewFrame(FrameType.DEVICE_INFORMATION_FRAME)?.let {
it as DeviceStaticInfoFrame
}
if (deviceInforFrame != null) {
//设备mac地址
val macAddress = deviceInforFrame.macAddress
//电量百分比
val battery = deviceInforFrame.battery
//固件版本
val firmwareVersion = deviceInforFrame.firmwareVersion
}
if (industrialHtFrame != null) {
//传感器当前温度
val temperature = combinationFrame.temperature
val humidity = combinationFrame.humidity
//单位 为0表示摄氏度,为1表示华氏度
val unit = combinationFrame.unit
//type 0:ht,1:temp
val temperature = combinationFrame.type
//屏幕状态
val screenStatus = combinationFrame.screenStatus
//传感器状态
val sensorStatus = combinationFrame.sensorStatus
//标记状态
val markStatus = combinationFrame.markStatus
//传感器名称
val deviceName = combinationFrame.deviceName
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
PT100温度传感器设备有2种广播帧类型。
设备静态信息帧
DeviceStaticInfoFrame
名称 类型 说明 frameVersion int 设备类型 firmwareVersion String 固件版本 batteryLevel int 电池电量百分比 macAddress String 固件mac peripheralSupportInfo PeripheralSupportInfo 外设支持描述,包含设备产品id
工业温湿度帧
IndustrialHtFrame
名称 类型 说明 frameVersion int 设备类型 tempHumiVersion int pt100 温湿度帧版本 type int 传感器类型。0: 温湿度,1: 单温 unit int 温度单位 为0表示摄氏度,为1表示华氏度 temperature float 温度 humidity float 湿度 deviceName String 设备名称 markStatus int 标记状态,1标记,0正常 screenStatus int 屏幕状态: 1 屏幕异常,0正常 sensorStatus int 传感器状态: 1传感器异常,0正常
# 连接
连接前一般需要先停止扫描。sdk提供了连接和断开连接方法。
val manager = PT100SensorBleManager.getInstance()
//停止扫描
manager.stopScan(context)
//设置设备秘钥
val key="minewtech1234567"
manager.setSecretKey(key)
//连接,module为准备连接的设备
val module:PT100SensorEntity
manager.connect(context,module)
//断开连接。macAddress为设备mac
manager.disConnect(macAddress)
2
3
4
5
6
7
8
9
10
11
12
注意:连接设备前,请确认是否扫描到设备,如果没扫描到设备广播,调用连接方法,将连接失败。
在调用connect()
后,sdk中会对连接过程会有状态监听。
val manager = PT100SensorBleManager.getInstance()
manager.setOnConnStateListener { macAddress, bleConnectionState ->
when (it) {
BleConnectionState.Connecting -> {
Log.d("connectionListener", "Connecting")
}
BleConnectionState.Connected -> {
Log.d("connectionListener", "Connected")
}
BleConnectionState.AuthenticateSuccess ->{
Log.d("connectionListener", "AuthenticateSuccess")
//秘钥检验成功。
}
BleConnectionState.AuthenticateFail ->{
Log.d("connectionListener", "AuthenticateFail")
//秘钥检验失败。
}
BleConnectionState.ConnectComplete -> {
//连接完成,此时设备可进行读写操作
Log.d("connectionListener", "ConnectComplete")
}
BleConnectionState.Disconnect -> {
//连接失败或者设备断开连接会回调
Log.d("connectionListener", "Disconnect")
}
else -> {}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
在连接过程中,sdk会返回多个连接状态到app中,app需要做好处理。
- BleConnectionState.Connecting,BleConnectionState.Connected: 连接设备中,在这里状态下不要做耗时操作,因为此时在连接设备发现服务,并发送认证数据等。
- BleConnectionState.ConnectComplete: 此时传感器设备已经连接成功,可以进行读写操作,比如配置广播参数、传感器配置、读取历史数据等。
- BleConnectionState.AuthenticateFail:认证过程中校验秘钥,输入的秘钥不正确,将回调这个状态并且设备主动断开连接。
- BleConnectionState.AuthenticateSuccess:认证过程中校验秘钥,输入的秘钥正确,将回调这个状态。
- BleConnectionState.Disconnect: 连接失败或者设备断开连接会回调。
# 读写
读写API如下:
/**
* 设置设备秘钥
* @param macAddress 设备mac
* @param secretKey 秘钥key
* @param listener
*/
public void setDeviceSecretKey(String macAddress, String secretKey, OnModifyConfigurationListener listener);
/**
* 查询设备版本信息
* @param macAddress 设备mac
* @param listener 监听器
*/
public void queryDeviceFirmwareInfo(String macAddress, OnQueryResultListener<FirmwareVersionModel> listener);
/**
* 读取历史数据
*
* @param macAddress 设备mac
* @param startTime 起始时间戳 单位:秒
* @param endTime 结束时间戳 单位:秒
* @param systemTime 实时时间戳 单位:秒
* @param listener 监听器
*/
public void queryHistoryData(String macAddress,long startTime,long endTime,long systemTime, OnQueryResultListener<HistoryHtData> listener);
/**
* 查询广播帧广播参数
* @param macAddress 设备mac
* @param slot 查询广播的通道值,默认值0
* @param listener 监听器
*/
public void queryAdvParametersConfiguration(String macAddress,int slot, OnQueryResultListener<AdvParametersConfiguration> listener);
/**
* 设置广播帧广播参数
*
* @param macAddress 设备mac
* @param frameType FrameType枚举获取
* @param slotNumber 设置广播对应的通道值
* @param advertisingInterval 广播间隔 单位毫秒,广播间隔 1s ~ 60s 可调,刻度为 1s;
* @param isAlwaysAdv 是否持续广播,0:持续广播,1:触发广播;
* @param txPower -40 -20 -16 -12 -8 -4 0 4dBm
* @param advertisingName 工业温湿度帧传,设置信息帧不需要传,
* @param listener 监听器
*/
void setAdvParametersConfiguration(@NonNull String macAddress, @NonNull String frameType, int slotNumber, int advertisingInterval, int isAlwaysAdv, int txPower, @Nullable String advertisingName, OnModifyConfigurationListener listener);
/**
* 设置温度单位
*
* @param macAddress 设备mac
* @param unit 1华氏,0摄氏
* @param listener 监听器
*/
void setTemperatureUnit(@NonNull String macAddress, int unit, OnModifyConfigurationListener listener);
/**
* 读取温度单位
*
* @param macAddress 设备mac
* @param listener 监听器
*/
void queryTemperatureUnit(@NonNull String macAddress, OnQueryResultListener<Integer> listener);
/**
* 设置工业温湿度传感器配置
*
* @param macAddress 设备mac
* @param htSettingData 触发阈值list 固定长度2
* @param samplingInterval 采样间隔 单位秒
* @param delayRecordInterval 延迟记录间隔 单位秒
* @param listener 监听器
*/
public void setHTSensorConfiguration(String macAddress, List<HTSensorThresholdConfig> htSettingData, int samplingInterval,int delayRecordInterval,OnModifyConfigurationListener listener);
/**
* 查询温湿度传感器配置
*
* @param macAddress 设备mac
* @param listener 监听器
*/
public void queryHTSensorConfiguration(String macAddress, OnQueryResultListener<HtSensorConfiguration> listener);
/**
* 固件升级
*
* @param macAddress 设备mac
* @param isLinkUpgrade true url升级,false 固件包升级。默认值false,不支持url升级方式
* @param dfuTarget isLinkUpgrade =true, dfuTarget = 0
* @param upgradeData 升级包数据
* @param listener 监听器
*/
public void firmwareUpgrade(String macAddress,boolean isLinkUpgrade,int dfuTarget,byte[] upgradeData, OnFirmwareUpgradeListener listener);
/**String macAddress
* 恢复出厂设置
*
* @param macAddress 设备mac
* @param listener 监听器
*/
public void reset(String macAddress, OnModifyConfigurationListener listener);
/**
* 关机
* @param macAddress 设备mac
* @param listener 监听器
*/
public void powerOff(String macAddress, OnModifyConfigurationListener listener);
/**
* 校验OTA升级文件的正确性
* @param zipFilePath ota升级文件路径
* @return true=升级文件,false= 不是升级文件
*/
boolean verifyOtaFile(@NonNull String zipFilePath);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
对部分方法进行补充说明:
设置设备秘钥。
val manager = PT100SensorBleManager.getInstance() val secretKey = "3141592653589793" manager.setSecretKey(mAddress,secretKey)
1
2
3
4查询设备版本信息。
suspend fun queryFirmwareInfo(): FirmwareVersionModel? = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext null } return@withContext suspendCancellableCoroutine<FirmwareVersionModel?> { continuation -> manager.queryDeviceFirmwareInfo(connectMacAddress!!) { isSuccessful, version -> continuation.resume( when (isSuccessful) { true -> version else -> null }, null ) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17查询设置设备温度
//1华氏温度,2摄氏温度 suspend fun queryTemperatureUnit(): Int = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext 0 } return@withContext suspendCancellableCoroutine<Int> { continuation -> manager.queryTemperatureUnit(connectMacAddress!!) { _, unit -> continuation.resume(unit, null) } } } suspend fun setTemperatureUnit(tempUnit: Int): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.setTemperatureUnit(connectMacAddress!!, tempUnit) { result -> continuation.resume(result, null) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23查询广播帧广播参数和配置广播参数。
//slot = 0 DeviceStaticInfoFrame 、slot = 1 IndustrialHtFrame /** * 读取广播参数配置 * @return Boolean */ suspend fun queryAdvertisingParametersConfiguration(slot: Int): AdvParametersConfig? = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext null } return@withContext suspendCancellableCoroutine<AdvParametersConfig?> { continuation -> manager.queryAdvParametersConfiguration( connectMacAddress!!, slot ) { isSuccessful, configResult -> continuation.resume( when (isSuccessful) { true -> configResult else -> null }, null ) } } } /** * 设置广播参数配置 * @return Boolean */ suspend fun setAdvertisingParametersConfiguration(slot:Int,frameType: String,advertisingInterval:Int, txPower:Int,isAlwaysAdv:Int,advertisingName:String?): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.setAdvParametersConfiguration(connectMacAddress!!,frameType,slot,advertisingInterval,isAlwaysAdv,txPower,advertisingName) { isSuccess -> continuation.resume(isSuccess, null) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42查询温度历史数据
/** * 读取历史数据 * * @param macAddress 设备mac * @param startTime 起始时间戳 单位:秒 * @param endTime 结束时间戳 单位:秒 * @param systemTime 实时时间戳 单位:秒 * @return HistoryHtData 温度数据 */ suspend fun readHistoryData(startTime:Long,endTime:Long,systemTime:Long): HistoryHtData?= withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext null } return@withContext suspendCancellableCoroutine<HistoryHtData?> { continuation -> manager.queryHistoryData(connectMacAddress!!,startTime,endTime,systemTime) { result,historyData -> continuation.resume(historyData, null) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20查询传感器参数和配置传感器参数。
//查询传感器参数 private fun queryHTSensorConfiguration() { lifecycleScope.launch(Dispatchers.Main) { WaitDialog.show(R.string.common_configing) val htSensorConfiguration = mConnectViewModel.queryHTSensorConfiguration() mHtSensorConfiguration = htSensorConfiguration WaitDialog.dismiss() val sb = StringBuilder() htSensorConfiguration?.let { //2组温度阈值数据 val htSettingData = it.htSettingData //温度报警1 val temp1Status = it.htSettingData[0].lowTemperature != -32768f && it.htSettingData[0].highTemperature != -32768f val temp2Status = it.htSettingData[1].lowTemperature != -32768f && it.htSettingData[1].highTemperature != -32768f when (temp1Status) { true -> { val temperatureAlarmLow1 = when (settingTemperatureUnit) { 1 -> getF(it.htSettingData[0].lowTemperature) else -> it.htSettingData[0].lowTemperature } val temperatureAlarmHigh1 = when (settingTemperatureUnit) { 1 -> getF(it.htSettingData[0].highTemperature) else -> it.htSettingData[0].highTemperature } val temp1Group = when (settingTemperatureUnit) { 1 -> "${temperatureAlarmLow1}°F ~ ${temperatureAlarmHigh1}°F" else -> "${temperatureAlarmLow1}°C ~ ${temperatureAlarmHigh1}°C" } sb.append("temp1Group=${temp1Group},\n") } else -> { val temp1Group = "~~" sb.append("temp1Group=${temp1Group},\n") } } when (temp2Status) { true -> { val temperatureAlarmLow2 = when (settingTemperatureUnit) { 1 -> getF(it.htSettingData[1].lowTemperature) else -> it.htSettingData[1].lowTemperature } val temperatureAlarmHigh2 = when (settingTemperatureUnit) { 1 -> getF(it.htSettingData[1].highTemperature) else -> it.htSettingData[1].highTemperature } val temp2Group = when (settingTemperatureUnit) { 1 -> "${temperatureAlarmLow2}°F ~ ${temperatureAlarmHigh2}°F" else -> "${temperatureAlarmLow2}°C ~ ${temperatureAlarmHigh2}°C" } sb.append("temp2Group=${temp2Group},\n") } else -> { val temp2Group = "~~" sb.append("temp2Group=${temp2Group},\n") } } //采集间隔。单位秒 val samplingInterval = it.samplingInterval //延迟记录时间。单位秒. val delayRecordTimeStamp = it.delay sb.append("samplingInterval=${samplingInterval},\n") sb.append("delayRecordTimeStamp=${delayRecordTimeStamp},\n") MessageDialog.show(getString(R.string.common_tips),"SensorConfiguration = ${sb.toString()}") } } } suspend fun queryHTSensorConfiguration(): HtSensorConfiguration? = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext null } return@withContext suspendCancellableCoroutine<HtSensorConfiguration?> { continuation -> manager.queryHTSensorConfiguration(connectMacAddress!!) { isSuccessful, configResult -> continuation.resume( when (isSuccessful) { true -> configResult else -> null }, null ) } } } //设置传感器参数 //2组温度阈值范围[-200,200],单位摄氏度。华氏范围自行换算,调用getF()。 private fun setHTSensorConfiguration(){ lifecycleScope.launch(Dispatchers.Main){ mHtSensorConfiguration?.let { WaitDialog.show(R.string.common_configing) val result = mConnectViewModel.setHTSensorConfiguration(it.htSettingData,it.samplingInterval,it.delay) WaitDialog.dismiss() ToastUtils.showShort(when(result){ true -> R.string.common_config_success else -> R.string.common_config_fail }) } } } private fun getF(t: Float): Float { return t * 1.8f + 32 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105固件升级。
private fun firmwareUpgrade( fileByte: ByteArray, dfuTarget: Int ) { mConnectViewModel.firmwareUpgrade(dfuTarget, fileByte, progressCallBack = { progress -> WaitDialog.show(getString(R.string.common_upgrading), (progress / 100f)) binding.progressBarSimpleCustom.progress = progress.toFloat() }, successCallBack = { WaitDialog.dismiss() ToastUtils.showShort(R.string.common_firmware_upgrade_successfully) finishPageForResult() }, failCallBack = { WaitDialog.dismiss() ToastUtils.showShort(R.string.common_firmware_upgrade_failure2) } ) } fun firmwareUpgrade( dfuTarget: Int, fileByte: ByteArray, progressCallBack:(progress:Int) -> Unit, successCallBack:() -> Unit, failCallBack:() -> Unit, ){ manager.firmwareUpgrade(connectMacAddress!!,false,dfuTarget,fileByte, object : OnFirmwareUpgradeListener { override fun updateProgress(progress: Int) { progressCallBack(progress) } override fun upgradeSuccess() { successCallBack() } override fun upgradeFailed() { failCallBack() } }) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46恢复出厂设置
suspend fun reset(): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.reset(connectMacAddress!!) { continuation.resume(it, null) } } }
1
2
3
4
5
6
7
8
9
10关机。
suspend fun shutdown(): Boolean = withContext(Dispatchers.Default) { if (connectMacAddress == null) { return@withContext false } return@withContext suspendCancellableCoroutine<Boolean> { continuation -> manager.powerOff(connectMacAddress!!) { continuation.resume(it, null) } } }
1
2
3
4
5
6
7
8
9
10
# 历史记录
- **2024/10/12 添加编辑文档;