# MTSensorV3Kit说明文档
本套SDK仅支持Minew公司出品的蓝牙Sensor设备,目前是温湿度传感器。通过SDK可以帮助开发者处理手机和Sensor之间的一切工作,包括:扫描设备,连接设备,向设备写入数据,从设备接收数据等。
# 前期工作
整体框架:MTCentralManager为设备管理类,在APP运行时始终是单例。MTPeripheral是设备实例类,此套件会为每一个设备生成一个MTPeripheral实例以便于对监听设备和操作设备。
MTCentralManager:设备管理类,可以扫描周围的Sensor设备,并且可以连接它们,校验它们等。
MTPeripheral:设备实例类,当MTCentralManager发现一个物理设备时,MTCentralManager会生成一个MTPeripheral实例,这个实例就对应一个物理设备。
MTBroadcastHandler:设备广播类,可以获取设备广播时的数据。
MTConnectionHandler:设备连接类,进行设备的接发数据。
MTSensorHandler:传感器操作类,进行设备的读写数据。
# 开始上手
# 开发环境:
- Xcode10+,当前SDK使用Xcode11编译,请使用Xcode10及以上版本进行开发;
- iOS12.0,限制最低系统版本为iOS12;
# 导入到工程:
手动导入
- 将开发套件的文件:MTSensorV3Kit.framework文件拷贝到项目工程目录下,然后添加到项目中。
PS:
- !!!在iOS10及以上版本,苹果对蓝牙APi添加了权限限制,你需要在工程的info.plist文件里添加一项字符串:Privacy - Bluetooth Peripheral Usage Description - "你的使用描述"。
- !!!在iOS13及以上版本,苹果对蓝牙APi添加了权限限制,你需要在工程的info.plist文件里添加一项字符串:Privacy - Bluetooth Always Usage Description - "你的使用描述"。
# 开始开发
# 扫描设备
首先需要获取到MTCentralManager的单例,然后检查手机当前的蓝牙状态,接着就可以进行设备扫描了。
// 获取Manager单例
MTCentralManagerV3 *manager = [MTCentralManagerV3 sharedInstance];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 手机端当前的蓝牙开关状态
if(self->manager.status == PowerStatePoweredOn) {
// 开始进行设备扫描
[manager startScan:^(NSArray<MTPeripheral *> *peripherals) {
//可根据broadcast属性的type筛选所需要的传感器种类
self->deviceAry = peripherals;
}];
}
});
//扫描到的设备也可以使用manager.scannedPeris获得
// 如果你需要对手机的蓝牙状态作出响应。请监听回调。
[manager didChangesBluetoothStatus:^(PowerState status){
switch(status) {
case PowerStatePoweredOn:
NSLog(@"bluetooth status change to poweron");
break;
case PowerStatePoweredOff:
NSLog(@"bluetooth status change to poweroff");
break;
case PowerStateUnknown:
NSLog(@"bluetooth status change to unknown");
}
}];
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
PS: 只有手机蓝牙状态处于Poweron时,整个SDK才能够正常工作。
# 连接到设备
// 从上一步能够获取到扫描到的设备
MTPeripheralV3 *device = deviceAry[0];
//连接设备
[manager connectToPeriperal:device];
// 监听设备连接状态。
[p.connector didChangeConnection:^(Connection connection) {
if (connection == Vaildated) {
//验证成功,成功连接设备
NSLog(@"vaildated");
//需要写入密码,密码验证成功后进行其他的操作
}
if (connection == Disconnected) {
NSLog(@"device has disconnected.");
}
}];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 向设备写入密码
接上一步,当手机成功与某个设备建立连接验证成功后,需要对设备写入密码,进行密码验证。
[device.connector.sensorHandler writePassword:@"minew123" completionHandler:^(BOOL success, MTRecieveErrorType errorType) {
if (success) {
NSLog(@"password is right");
//then do what you want for example:
} else {
NSLog(@"password is error");
}
}];
2
3
4
5
6
7
8
9
# 其他指令操作
接上一步,当设备成功验证写入的密码正确后,方可进行其他指令操作。
以下操作不分先后顺序,可自行选择。
# 获取设备信息
设备信息具体属性可见附表。
/// 获取设备信息
/// @param completionHandler 回调结果
[device.connector.sensorHandler readDeviceInfo:^(BOOL success, MTDeviceInfoData * _Nonnull data) {
if (success) {
NSLog(@"readDeviceData successfully");
NSString *firVersion = data.firmVersion;
NSInteger advTxpower = data.advTxpower;
BOOL isOpenTempAlarmSwitch = data.isOpenTempAlarmSwitch;
BOOL isOpenHumiAlarmSwitch = data.isOpenHumiAlarmSwitch;
double highTempAlarm = data.highTempAlarm;
double lowTempAlarm = data.lowTempAlarm;
double highHumiAlarm = data.highHumiAlarm;
double lowHumiAlarm = data.lowHumiAlarm;
double temperatureResolution = data.temperatureResolution;
double humidityResolution = data.humidityResolution;
double currentTemperature = data.currentTemperature;
double currentHumidity = data.currentHumidity;
MTTemperatureUnitType unitType = data.unitType;
BOOL isStorageSomethine = data.isStorageSomethine;
NSString *deviceName = data.deviceName;
NSLog(@"firVersion:%@, advTxpower:%ld, isOpenTempAlarmSwitch:%@, isOpenHumiAlarmSwitch:%@, highTempAlarm:%f, lowTempAlarm:%f, highHumiAlarm:%f, lowHumiAlarm:%f, temperatureResolution:%f, humidityResolution:%f, currentTemperature:%f, currentHumidity:%f, TemperatureUnitType:%@, isOpenStorageSwitch:%@, deviceName:%@", firVersion, advTxpower, isOpenTempAlarmSwitch==YES?@"Yes":@"No", isOpenHumiAlarmSwitch==YES?@"Yes":@"No", highTempAlarm, lowTempAlarm, highHumiAlarm, lowHumiAlarm, temperatureResolution, humidityResolution, currentTemperature, currentHumidity, unitType==Celsius?@"Celsius":@"Fahrenheit", isStorageSomethine==YES?@"Yes":@"No", deviceName);
if (data.deviceInfoType == MST01InfoOfHighVersion) {
NSInteger advIntervalForHTFrame = data.advIntervalForHTFrame;
NSInteger advIntervalForInfoFrame = data.advIntervalForInfoFrame;
NSLog(@"advIntervalForHTFrame:%ld, advIntervalForInfoFrame:%ld", advIntervalForHTFrame, advIntervalForInfoFrame);
} else {
NSInteger advInterval = data.advInterval;
NSLog(@"advInterval:%ld", advInterval);
}
} else {
NSLog(@"readDeviceData failed");
}
}];
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
# 设置设备名称
设置设备名称不得超过八位的数字/字母,不支持除数字/字母之外的类型。
/// 设置设备名称
/// @param deviceName 设备名称
/// @param completionHandler 回调结果
[device.connector.sensorHandler setDeviceName:@"minew123" completionHandler:^(BOOL success, MTRecieveErrorType errorType) {
if (success) {
NSLog(@"setDeviceName successfully");
}
else {
NSLog(@"setDeviceName failed");
}
}];
2
3
4
5
6
7
8
9
10
11
# 设置设备存储开关
设置 YES 表示开始存储数据,设置 NO 表示停止存储数据。
/// 设置设备存储开关
/// @param storageStatus 存储开关
/// @param completionHandler 回调结果
[device..connector.sensorHandler setStorageStatusOfHistoricalData:isStorage completionHandler:^(BOOL success) {
if (success) {
NSLog(@"setIsStorageData successfully");
}
else {
NSLog(@"setIsStorageData failed");
}
}];
2
3
4
5
6
7
8
9
10
11
# 设置温湿度传感器温度单位
温度单位分为摄氏温标(Celsius)和华氏温标(Fahrenheit)。
单位转换:摄氏度为 20 时,转换为华氏度值为 20*1.8+32 。
/// 设置温湿度传感器温度单位
/// @param temperatureUnitType 温度单位类型,Celsius 和 Fahrenheit
/// @param completionHandler 回调结果
[device.connector.sensorHandler setTemperatureUnit:Celsius completionHandler:^(BOOL success, MTRecieveErrorType errorType) {
if (success) {
NSLog(@"setTemperatureUnit successfully");
}
else {
NSLog(@"setTemperatureUnit failed");
}
}];
2
3
4
5
6
7
8
9
10
11
# 设置温湿度传感器警告上下界及警告开关
请注意,摄氏度单位下,温度最大为85°C,最小为-40°C,华氏度下,温度最大为185°F,最小为-40°F;湿度最大为100,最小为0。另外,警告区间上界值需要大于或等于下界值。
/// 设置温湿度传感器警告上下界及警告开关
/// @param maxTemp 温度上界
/// @param minTemp 温度下界
/// @param maxHumi 湿度上界
/// @param minHumi 湿度下界
/// @param isTempWarn 温度报警开关
/// @param isHumiWarn 湿度报警开关
/// @param completionHandler 回调结果
[device.connector.sensorHandler setHTWarningWithMaxTemp:hTemp minTemp:lTemp maxHumi:hHumi minHumi:lHumi isTempWarn:YES isHumiWarn:YES completionHandler:^(BOOL success) {
if (success) {
NSLog(@"setHTWarning successfully");
}
else {
NSLog(@"setHTWarning failed");
}
}];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 读取温湿度历史数据
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
[formatter setDateFormat:@"YYYY/MM/dd HH:mm:ss"];
//设置时区
NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"];
[formatter setTimeZone:timeZone];
/// 读取温湿度历史数据
/// @param formatter 日期格式
/// @param unit 温度单位
[device.connector.sensorHandler readHTHistoryWithDateFormatter:formatter Unit:Celsius completionHandler:^(BOOL success, NSInteger totalNum, NSArray<MTHistoryData *> * _Nonnull data) {
if (success) {
NSLog(@"Success to read ht history.");
for (int i = 0; i < data.count; i++) {
MTHistoryData *historyData = data[i];
NSLog(@"originData:%@, timeInterval:%f timeStr:%@, temp:%f, humi:%f", historyData.historyOriginData, historyData.timeInterval, historyData.timeStr, historyData.temp, historyData.humi);
// Historical data has been parsed within the SDK, but if you want to get the raw data and parse the data yourself, you can refer to the code.
}
} else {
NSLog(@"Failed to read ht history.");
}
}];
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
# 固件升级
请注意,需要使用匹配的固件升级包,否则可能导致设备无法正常使用。
// ⚠️注意:demo 附带的ota升级包未必与当前设备匹配,请根据自己手头设备的硬件及固件信息,跟业务沟通后,使用匹配的固件升级包进行 ota 升级。如果使用了错误的固件升级包,这可能会让你的设备无法正常使用。
// 只看s3 s4 关键词来区分固件升级包是否与设备匹配是不可行的,因为不同出厂设置的设备,固件版本和硬件版本也不一定匹配,所以一定要确认固件升级包的正确。
NSData *otaPacketData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"S3V2_NV900_20210312_s3_ota_v1_0_23" ofType:@".bin"]];
/// 固件升级
/// @param originOtaData 固件升级包数据
/// @param stateHandler 监听升级状态的改变,“完成”表示升级成功。
/// @param progressHandler 监听升级包发送进度
/// @param errorHandler 监听升级失败原因
[device.connector startOTAWithOTAData:otaPacketData stateHandler:^(OTAState state) {
if (state == OTAStateStarting) {
NSLog(@"ota start");
} else if(state == OTAStateUploading) {
NSLog(@"ota uploading");
} else if(state == OTAStateAborted) {
NSLog(@"ota aborted");
} else if(state == OTAStateDisconnecting) {
NSLog(@"ota disconnect");
} else if (state == OTAStateCompleted) {
NSLog(@"ota successfully");
} else if(state == OTAStateFailed) {
NSLog(@"ota failed");
}
} progressHandler:^(float progress) {
NSLog(@"ota progress:%f", progress);
} errorHandler:^(NSError * _Nonnull error) {
NSLog(@"ota failed,error:%@",error);
}];
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
# 工业温湿度计特殊配置
# 设置延时记录时间
请注意,延时时间为0-18h,最大时间能设置为18小时整,按键开机默认是10min,固件调整延时时间范围0-18h,支持10min以内时间设置。单位为秒。
/// 设置延时记录时间
/// @param delayTime 延时时间为0-18h,最大时间能设置为18小时整,按键开机默认是10min,固件调整延时时间范围0-18h,支持10min以内时间设置。单位为秒。
/// @param completionHandler 回调结果
[device.connector.sensorHandler setIndustrialHTWarningWithMaxTemp1:hTemp1 minTemp1:lTemp1 maxTemp2:hTemp2 minTemp2:lTemp2 maxHumi:hHumi minHumi:lHumi isTempWarn:YES isTempWarnSecond:YES isHumiWarn:YES completionHandler:^(BOOL success) {
if (success) {
NSLog(@"setIndustrialHTWarning successfully");
}
else {
NSLog(@"setIndustrialHTWarning failed");
}
}];
2
3
4
5
6
7
8
9
10
11
# 设置广播功率
请注意,广播功率的值只能设置 -40, -20, -16, -12, -8, -4, 0, 4。
/// 设置广播功率
/// @param broadcastPower 广播功率。广播功率的值只能设置 -40, -20, -16, -12, -8, -4, 0, 4 dbm
/// @param completionHandler 回调结果
[device.connector.sensorHandler setBroadcastPower:-40 CompletionHandle:^(BOOL success) {
if (success) {
NSLog(@"setBroadcastPower successfully");
}
else {
NSLog(@"setBroadcastPower failed");
}
}];
2
3
4
5
6
7
8
9
10
11
# 设置广播间隔
请注意,工业温湿度固件版本号为3.1.0以下设备,和S3-V3设备可使用该指令。广播间隔范围为 100 - 5000ms。
/// 设置广播间隔
/// @param broadcastInterval 广播间隔。广播间隔范围为 100 - 5000ms
/// @param completionHandler 回调结果
[device.connector.sensorHandler setBroadcastInterval:1000 CompletionHandle:^(BOOL success) {
if (success) {
NSLog(@"setBroadcastInterval successfully");
}
else {
NSLog(@"setBroadcsetBroadcastIntervalastPower failed");
}
}];
2
3
4
5
6
7
8
9
10
11
请注意,工业温湿度,固件版本3.1.0及以上设备,使用以下指令设置广播间隔。
/// 设置广播间隔,工业温湿度,固件版本3.1.0及以上设备使用该指令
/// @param broadcastIntervalForHTFrame 温湿度广播帧的广播间隔,范围为 1000-60000ms.
/// @param broadcastIntervalForDeviceInfoFrame 设备信息帧的广播间隔,范围为 100-5000ms.
[device.connector.sensorHandler setBroadcastIntervalForHTFrame:1000 BroadcastIntervalForDeviceInfoFrame:500 CompletionHandle:^(BOOL success) {
if (success) {
NSLog(@"setBroadcastIntervalForMST01HighFirmVersion successfully");
}
else {
NSLog(@"setBroadcsetIntervalForMST01HighFirmVersion failed");
}
}];
2
3
4
5
6
7
8
9
10
11
# 设置采集间隔
请注意,采集间隔范围为 1s--24h,单位为秒。
/// 设置采集间隔
/// @param collectInterval 广播间隔。广播间隔范围为 1s--24h,单位为秒
[device.connector.sensorHandler setCollectInterval:30 CompletionHandle:^(BOOL success) {
if (success) {
NSLog(@"setCollectIntervalForMST01HighFirmVersion successfully");
}
else {
NSLog(@"setCollectIntervalForMST01HighFirmVersion failed");
}
}];
2
3
4
5
6
7
8
9
10
# 设置温湿度告警区间及告警开关
请注意,摄氏度单位下,温度最大为85°C,最小为-40°C,华氏度下,温度最大为185°F,最小为-40°F;湿度最大为100,最小为0。另外,警告区间上界值需要大于或等于下界值。
/// Set alarm temperature and humidity for industrial device
/// @param maxTemp1 温度1上界
/// @param minTemp1 温度1下界
/// @param maxTemp2 温度2上界
/// @param minTemp2 温度2下界
/// @param maxHumi 湿度上界
/// @param minHumi 湿度下界
/// @param isTempWarn 温度1报警开关
/// @param isTempWarnSecond 温度2报警开关
/// @param isHumiWarn 湿度报警开关
/// @param completionHandler 回调结果
[device.connector.sensorHandler setIndustrialHTWarningWithMaxTemp1:hTemp1 minTemp1:lTemp1 maxTemp2:hTemp2 minTemp2:lTemp2 maxHumi:hHumi minHumi:lHumi isTempWarn:YES isTempWarnSecond:YES isHumiWarn:YES completionHandler:^(BOOL success) {
if (success) {
NSLog(@"setIndustrialHTWarning successfully");
}
else {
NSLog(@"setIndustrialHTWarning failed");
}
}];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
附表
# MTCentralManager 属性说明
名称 | 类型 | 备注 |
---|---|---|
state | PowerState | 当前的手机蓝牙状态 |
scannedPeris | NSArray | 扫描到的设备 |
# MTPeripheral属性说明
名称 | 类型 | 备注 |
---|---|---|
identifier | NSString | 设备的Identifier |
broadcast | MTBroadcastHandler | 广播类实例对象 |
connector | MTConnectionHandler | 连接类实例对象 |
# MTBroadcastHanler属性说明
名称 | 类型 | 备注 |
---|---|---|
name | NSString | 设备的蓝牙名称 |
rssi | NSInteger | 设备的RSSI |
battery | NSString | 设备的电池电量 |
mac | NSString | 设备的Mac地址 |
identifier | NSString | 设备的识别码 |
temp | double | 设备温度 |
humi | double | 设备湿度 |
reseInfo | uint8_t | 设备温度单位标识符 |
type | SensorType | 设备类型 |
doorStatus | NSString | 门磁设备门磁状态 |
warningStatus | uint8_t | 设备报警状态 |
# MTConnectionHandler属性说明
名称 | 类型 | 备注 |
---|---|---|
macString | NSString | 设备Mac地址 |
connection | Connection | 设备连接状态 |
sensorHandler | MTSensorHandlerV3 | 传感器读写操作管理 |
# MTDeviceInfo属性说明
名称 | 类型 | 备注 |
---|---|---|
firmVersion | NSString | 固件版本 |
advInterval | NSInteger | 广播间隔,ms |
advTxpower | NSInteger | 广播功率 |
isOpenTempAlarmSwitch | BOOL | 温度告警开关1 |
isOpenHumiAlarmSwitch | BOOL | 湿度告警开关 |
highTempAlarm | double | 温度告警上界1 |
lowTempAlarm | double | 温度告警下界1 |
highHumiAlarm | double | 湿度告警上界 |
lowHumiAlarm | double | 湿度告警下界 |
temperatureResolution | double | 温度分辨率 |
humidityResolution | double | 湿度分辨率 |
currentTemperature | double | 实时温度 |
currentHumidity | double | 实时湿度 |
unitType | MTTemperatureUnitType | Celsius:摄氏度,Fahrenheit:华氏度 |
isStorage | BOOL | NO 为停止存储,YES 为开始存储 |
deviceName | NSString | 设备名称 |
delayRecordTime | int | 延时记录时间,单位是秒 |
isOpenTempAlarmSwitchSecond | BOOL | 温度报警开关2 |
secondHighTempAlarm | double | 温度告警上界2 |
secondLowTempAlarm | double | 温度告警下界2 |
advIntervalForHTFrame | NSInteger | 温湿度广播帧的广播间隔,ms, 仅当固件版本3.1.0及以上工业温湿度设备 |
advIntervalForInfoFrame | NSInteger | 设备信息帧的广播间隔,ms, 仅当固件版本3.1.0及以上工业温湿度设备 |
deviceInfoType | MTDeviceInfoType | MST01Info, PR2122Info, MST01InfoOfHighVersion |
# MTHistoryData属性说明
名称 | 类型 | 备注 |
---|---|---|
historyOriginData | NSData | 未解析的历史数据 |
humi | double | 湿度数值 |
temp | double | 湿度数值 |
timeStr | NSString | 格式化的时间字符串 |
timeInterval | NSTimeInterval | 未格式化的时间 |
# 注意事项
在开发过程中你可能会发现,持续扫描一段时间,有些设备会出现多个MTPeripheral实例。关于这一点,我们咨询过苹果工程师。得到的答复是在目前的iOS平台下,CoreBluetooth对多通道广播(特别是广播数据在变化)设备并不友好。
iOS11中此问题已不再存在。
如果添加SDK之后,运行显示无法找到路径,可以在 General -> Frameworks,Libraries,and Embedded Content ,把 MSensorV3Kit.framework -> Embed,从 ‘Do Not Embed’ 改为 ‘Embed & Sign’ 即可。
同时写入多条指令可能会导致异常,建议每条指令完成后,再写入新的指令。
# 文档版本记录
- 2022.05.12 v1.0 初版;
- 2022.8.31 v1.0.1 第二版;