# RadarSensorKit说明文档
本套SDK仅支持Minew公司出品的蓝牙Sensor设备,目前是工业温湿度传感器。通过SDK可以帮助开发者处理手机和Sensor之间的一切工作,包括:扫描设备,连接设备,向设备写入数据,从设备接收数据等。
# 前期工作
整体框架:MTICentralManager为设备管理类,在APP运行时始终是单例。MTIPeripheral是设备实例类,此套件会为每一个设备生成一个MTIPeripheral实例以便于对监听设备和操作设备。
MTICentralManager:设备管理类,可以扫描周围的Sensor设备,并且可以连接它们,校验它们等。
MTIPeripheral:设备实例类,当MTICentralManager发现一个物理设备时,MTICentralManager会生成一个MTIPeripheral实例,这个实例就对应一个物理设备。
MTIFrameHandler:设备广播类,可以获取设备广播时的数据。
MTConnectionHandler:设备连接类,进行设备的接发数据。
MTISensorHandler:传感器操作类,进行设备的读写数据。
# 开始上手
# 开发环境:
- Xcode10+,当前SDK使用Xcode15编译,请使用Xcode10及以上版本进行开发;
- iOS12.0,限制最低系统版本为iOS12;
# 导入到工程:
手动导入
- 将开发套件的文件:MTIndustrialSensorKit.framework文件拷贝到项目工程目录下,然后添加到项目中。
PS:
- !!!在iOS10及以上版本,苹果对蓝牙APi添加了权限限制,你需要在工程的info.plist文件里添加一项字符串:Privacy - Bluetooth Peripheral Usage Description - "你的使用描述"。
- !!!在iOS13及以上版本,苹果对蓝牙APi添加了权限限制,你需要在工程的info.plist文件里添加一项字符串:Privacy - Bluetooth Always Usage Description - "你的使用描述"。
# 开始开发
# 扫描设备
首先需要获取到MTICentralManager的单例,然后检查手机当前的蓝牙状态,接着就可以进行设备扫描了。
// 获取Manager单例
MTICentralManager *manager = [MTICentralManager 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<MTIPeripheral *> *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");
}
}];
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
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才能够正常工作。
# 连接到设备
// 从上一步能够获取到扫描到的设备
MTIPeripheral *device = deviceAry[0];
//连接设备
[manager connectToPeriperal:device SecretKey:@"Device's secretKey"];
// 监听设备连接状态。
[device.connector didChangeConnection:^(Connection connection) {
if (connection == Vaildated) {
//验证成功,成功连接设备
NSLog(@"vaildated");
//需要写入密码,密码验证成功后进行其他的操作
}
if (connection == Disconnected) {
NSLog(@"device has disconnected.");
}
}];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 帧类型
MTIFrame *frame = device.frameHandler.advFrames[0];
if (frame.frameType == MTIFrameDeviceInfo) {
MTIDeviceInfoFrame *deviceInfoFrame = (MTIDeviceInfoFrame *)frame;
} else if (frame.frameType == MTIFrameCoordinateInfo) { // 会议室
MTICoordinateInfoFrame *coordinateFrame = (MTICoordinateInfoFrame *)frame;
NSLog(@"坐标 mac:%@, 人数:%d", device.frameHandler.mac, coordinateFrame.totalNumberOfPerson);
} else if (frame.frameType == MTIFrameTrafficMonitoring) { // 人流量
MTITrafficMonitoringFrame *trafficMonitoringFrame = (MTITrafficMonitoringFrame *)frame;
NSLog(@"mac: %@ 序列号:%d, 进门次数:%d,出门次数:%d", device.frameHandler.mac, trafficMonitoringFrame.serialNumber, trafficMonitoringFrame.numberOfEntries, trafficMonitoringFrame.numberOfExits);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 其他指令操作
接上一步,当设备成功验证写入的密钥正确后,方可进行其他指令操作。
以下操作不分先后顺序,可自行选择。
# 恢复蓝牙出厂设置
/// 恢复蓝牙出厂设置
[device.connector.radarSensorHandler resetDevice:^(BOOL success) {
if (success){
// 成功后断开蓝牙
[[MTICentralManager sharedInstance] disconnectFromPeriperal:self->device];
}else{
NSLog(@"failed");
}
}];
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 恢复雷达出厂设置
/// 恢复蓝牙出厂设置
/// @param RadarType MTRadarInfoType
[device.connector.radarSensorHandler restoreDeviceWithRadarType:self.radarInfoType CompletionHandler:^(BOOL success) {
if (success){
// 成功后断开蓝牙
[[MTICentralManager sharedInstance] disconnectFromPeriperal:self->device];
}else{
NSLog(@"failed");
}
}];
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 获取设备信息帧的广播参数
/// 获取设备信息帧的广播参数
/// @param completionHandler 结果回调
[device.connector.radarSensorHandler getDeviceInfoFrameAdvertisingParameters:^(BOOL success, MTIAdvertisingParametersData * _Nonnull data) {
if (success) {
NSLog(@"信息帧类型:%@,广播间隔:%ld, 广播功率:%d,持续广播:%@", data.frameType == MTIFrameDeviceInfo ? @"设备信息帧":@"组合帧", data.advertisingInterval, data.txPower, data.isAlwaysAdvertising == YES ? @"是的":@"不是");
}
}];
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 设置设备信息帧的广播参数
请注意,广播功率的值只能设置 -40, -20, -16, -12, -8, -4, 0, 4。
int interval = 100; // unit is ms.
int txpower = 4;
/// 设置设备信息帧的广播参数
/// @param advertisingInterval 广播间隔,单位为毫秒
/// @param txPower -40 -20 -16 -12 -8 -4 0 4dBm
/// @param completionHandler 结果回调
[device.connector.radarSensorHandler setDeviceInfoFrameAdvertisingParametersConfiguration:interval TxPower:txpower CompletionHandle:^(BOOL success) {
if (success) {
NSLog(@"设置设备信息帧配置参数:成功");
} else {
NSLog(@"设置设备信息帧配置参数:失败");
}
}];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 获取雷达参数配置
/// Get radar sensor's configuration
/// @param completionHandler the receive block.
[device.connector.radarSensorHandler getRadarSensorConfiguration:^(BOOL success, MTRadarInfoType infoType, MTMillimeterRadarSensorInfo * _Nonnull millimeterRadarSensorInfo) {
NSLog(@"millimeterRadarSensorInfo:%@", millimeterRadarSensorInfo);
if (infoType == MTRadarInfoTypePeople) {
MTRTrafficMonitorRadarSensorInfo *info = (MTRTrafficMonitorRadarSensorInfo *)millimeterRadarSensorInfo;
NSLog(@"工作模式:%@", info.infoDic[TrafficMonitorRadarSensorInfoTypeStringMap(TMRIRadialDistance)]);
} else if(infoType == MTRadarInfoTypeCoordinate) {
MTRCoordinateRadarSensorInfo *info = (MTRCoordinateRadarSensorInfo *)millimeterRadarSensorInfo;
NSLog(@"波特率:%@", info.infoDic[CoordinateRadarSensorInfoTypeStringMap(CRIBoutRate)]);
}
}];
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 设置雷达参数配置
/// Set radar sensor configuration
/// @param completionHandler the receive block.
[device.connector.radarSensorHandler setRadarSensorConfigurationWithCommandDic:commandDic RadarType:self.radarInfoType CompletionHandler:^(BOOL success, NSError * _Nonnull error) {
if (success) {
// "设置成功"
} else {
// "设置失败"
}
}];
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 固件升级
请注意,需要使用匹配的固件升级包,否则可能导致设备无法正常使用。
// ⚠️注意:demo 附带的ota升级包未必与当前设备匹配,请根据自己手头设备的硬件及固件信息,跟业务沟通后,使用匹配的固件升级包进行 ota 升级。如果使用了错误的固件升级包,这可能会让你的设备无法正常使用。
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);
}];
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
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
# 注意事项
- 同时写入多条指令可能会导致异常,建议每条指令完成后,再写入新的指令。
# 文档版本记录
- 2024.03.20 v1.0 初版;