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;

导入到工程:

  1. 手动导入

    • 将开发套件的文件:MTSensorV3Kit.framework文件拷贝到项目工程目录下,然后添加到项目中。

PS:

  1. !!!在iOS10及以上版本,苹果对蓝牙APi添加了权限限制,你需要在工程的info.plist文件里添加一项字符串:Privacy - Bluetooth Peripheral Usage Description - "你的使用描述"。
  2. !!!在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");
    }
}];
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

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.");
    }
}];
1
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");
        }
    }];

1
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 advInterval = data.advInterval;
            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:%@, advInterval:%ld, advTxpower:%ld, isOpenTempAlarmSwitch:%@, isOpenHumiAlarmSwitch:%@, highTempAlarm:%f, lowTempAlarm:%f, highHumiAlarm:%f, lowHumiAlarm:%f, temperatureResolution:%f, humidityResolution:%f, currentTemperature:%f, currentHumidity:%f, TemperatureUnitType:%@, isOpenStorageSwitch:%@, deviceName:%@", firVersion, advInterval, 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);
            
        } else {
            NSLog(@"readDeviceData  failed");
        }
    }];
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
设置设备名称

设置设备名称不得超过八位的数字/字母,不支持除数字/字母之外的类型。

    /// 设置设备名称
    /// @param deviceName 设备名称
    /// @param completionHandler 回调结果
    [device.connector.sensorHandler setDeviceName:@"minew123" completionHandler:^(BOOL success, MTRecieveErrorType errorType) {
        if (success) {
            NSLog(@"setDeviceName successfully");
        }
        else {
            NSLog(@"setDeviceName failed");
        }
    }];
1
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");
            }
    }];
1
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");
        }
    }];
1
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");
        }
    }];
1
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.");
        }
        
    }];
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
固件升级

请注意,需要使用匹配的固件升级包,否则可能导致设备无法正常使用。

    // ⚠️注意: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);
    }];
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

工业温湿度计特殊配置

设置延时记录时间

请注意,延时时间为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");
        }
    }];
1
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");
        }
    }];
1
2
3
4
5
6
7
8
9
10
11
设置广播间隔

请注意,广播间隔范围为 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");
        }
    }];
1
2
3
4
5
6
7
8
9
10
11
设置温湿度告警区间及告警开关

请注意,摄氏度单位下,温度最大为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");
        }
    }];
1
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
MTHistoryData属性说明
名称 类型 备注
historyOriginData NSData 未解析的历史数据
humi double 湿度数值
temp double 湿度数值
timeStr NSString 格式化的时间字符串
timeInterval NSTimeInterval 未格式化的时间

注意事项

  1. 在开发过程中你可能会发现,持续扫描一段时间,有些设备会出现多个MTPeripheral实例。关于这一点,我们咨询过苹果工程师。得到的答复是在目前的iOS平台下,CoreBluetooth对多通道广播(特别是广播数据在变化)设备并不友好。

    iOS11中此问题已不再存在。

  2. 如果添加SDK之后,运行显示无法找到路径,可以在 General -> Frameworks,Libraries,and Embedded Content ,把 MSensorV3Kit.framework -> Embed,从 ‘Do Not Embed’ 改为 ‘Embed & Sign’ 即可。

  3. 同时写入多条指令可能会导致异常,建议每条指令完成后,再写入新的指令。

文档版本记录

  • 2022.05.12 v1.0 初版;
上次更新:: 2022/6/1下午3:55:40