当前位置: 首页 > news >正文

ios 通过搜索设备MAC地址绑定

最近做了一个物联网项目,涉及到了设备绑定配网这块,需要了解一下iOS BLE与设备绑定的相关知识点,第一次接触蓝牙相关的项目,所以开始熟悉蓝牙的相关信息。没有去深入研究BabyTooth库,只是感觉CoreBluetooth已经让我更好的理解整个流程

这个物联网项目的设备绑定流程是需要APP端把WIFI的信息传给硬件设备,不过硬件存在一些瑕疵

  1. 硬件设备不会告诉APP端WIFI密码是否未填/错误

  1. 硬件设备不会告诉APP端设备是通过2.4G网络还是5G网络

  1. 设备属于同一个型号,但是设备支持的功能却不同,设备很混乱,例如一种配网功能有些需要2分钟内,有些不需要

  1. 子设备配网需要主设备在线,并且配网成功有WIFI信息才能正常使用

  1. 子设备的生产并没有合理化的展开,有些子设备的MAC是错误的,有些子设备有蓝牙名称有些没有

所以只能通过跑定时器60s来拟定设备绑定错误,且通过一个大量的文案提示来告诉用户错误的可能性,让用户自行判断是设备问题导致的无法配网还是因为WIFI频段的问题还是WIFI密码错误的问题等

参考了部分APP绑定硬件设备流程,标准流程都有,但是部分在配网页面是120s且不存在综合错误统计页面,最后的配网准备流程等待过长时间且没有过多的文案提示,对用户来说并不是很友好

项目中实用到的错误综合参考页面

故障拓展的因素种类过多,需要考虑的极限异常种类也很多,比如使用WIFI配网时网络突然中断,配网成功后网络出现波动等

总之,一个萝卜一个坑,为了保证用户在购买硬件产品后,不需要使用说明书就能实现APP操作硬件

用户体验,我辈义不容辞! ! !

目前的硬件设备想要配置网络使用的2.4G网络,也可以是2.4G和5G二合一的网络

关于WIFI 2.4G和5G状态的判断
尝试过使用WIFI信号的频道强度来获取当前连接的WIFI是2.4G和5G,并不适用
简单的通过WIFI的名称,通过获取到的字符串来识别是否包含2.4G和5G,需要判断逻辑考虑不全且没什么意义
  • 如果有好的方式,请私信联系我

一些注意事项

  1. 开启蓝牙模块,需要系统和APP的蓝牙全部开启

  1. 需要获取WIFI信息

  1. 地址定位权限需要开启,为什么呢?

在 iOS 13 当中,苹果增加了无线网络和蓝牙位置隐私保护,API 方面有所变化,并新增了控制选项,有助于在用户使用无线网络和蓝牙时,防止应用未经你同意而获取你的位置信息。
  • APP权限检测流程

#import <CoreBluetooth/CoreBluetooth.h>

外围设备和中央设备在CoreBluetooth中使用CBPeripheralManager和CBCentralManager表示。

CBPeripheralManager:外围设备通常用于发布服务、生成数据、保存数据。外围设备发布并广播服务,告诉周围的中央设备它的可用服务和特征。

CBCentralManager:中央设备使用外围设备的数据.中央设备扫描到外围设备后会就会试图建立连接,一旦连接成功就可以使用这些服务和特征。

外围设备和中央设备之间交互的桥梁是服务(CBService)和特征(CBCharacteristic)
获取当前手机的WIFI信息
-(void)makeWifiIsCanUes
{id info = nil;NSString *str ;NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();for (NSString *ifnam in ifs) {info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);str = info[@"SSID"];_BBIDdStr = info[@"BSSID"];NSLog(@"%@----",info);}if (str.length == 0) {NSLog(@" 您的手机还未连接WiFi网络");}else{self.ssidStr = [BZAirKissShareTools fetchSSIDInfo][@"SSID"];self.wifiName.text = [BZAirKissShareTools fetchSSIDInfo][@"SSID"];}
}

主设备是根据有指定的SN号可以配对的,所以在扫描周围设备方法的回调中对返回的peripheral.name

wifiNamePwd WIFI密码可以为空,但是WIFI名称是一定需要的
[self.centerManager scanDeviceWithTimeInterval:NSIntegerMax services:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey: @YES }  callBack:^(EasyPeripheral *peripheral, searchFlagType searchType) {NSLog(@"peripheral : %@ ",peripheral);NSLog(@"peripheral.name : %@ ",peripheral.name);NSLog(@"peripheral.identifier.UUIDString : %@ ",peripheral.identifier.UUIDString);NSData *data = [peripheral.advertisementData objectForKey:@"kCBAdvDataManufacturerData"];NSString *aStr= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];const char *valueString = [[data description] cStringUsingEncoding: NSUTF8StringEncoding];NSString *mac = [self convertToNSStringWithNSData:data];aStr = [aStr stringByReplacingOccurrencesOfString:@" " withString:@""];NSLog(@"aStr : %@",aStr);NSLog(@"advertisementData : %@",peripheral.advertisementData);NSLog(@"======================================================");NSLog(@"MAC : %@",mac);NSLog(@"======================================================");if ([peripheral.name containsString:self.sn.uppercaseString]) {[self.centerManager stopScanDevice];NSData *data =[self.wifiNamePwd dataUsingEncoding:NSUTF8StringEncoding];WEAKSELF;[self.characteristic writeValueWithData:data callback:^(EasyCharacteristic *characteristic, NSData *data, NSError *error) {NSLog(@"成功");if (error) {[weakSelf connectionBackWithType:1];}else{[weakSelf connectionBackWithType:0];}}];}}];self.centerManager.stateChangeCallback = ^(EasyCenterManager *manager, CBManagerState state) {NSLog(@"%ld",(long)state);};}

需要注意的是蓝牙模块的生态

1.蓝牙搜索

开始蓝牙搜索 - 蓝牙搜索中 - 蓝牙搜索成功

2.蓝牙连接

开始蓝牙连接 - 蓝牙连接中 - 蓝牙连接成功

3.WIFI连接

开始WIFI连接 - WIFI连接中 - WIFI连接成功

4.设备联网

设备联网中 - 设备联网成功

不使用蓝牙时需要取消关闭[self.peripheral disconnectDevice];[self.centerManager stopScanDevice];[self.centerManager disConnectAllDevice];[self.centerManager removeAllScanFoundDevice];
连上蓝牙配网
- (void)deviceConnect:(EasyPeripheral *)peripheral error:(NSError *)errorself.peripheral = peripheral;WEAKSELF;[self.peripheral discoverAllDeviceServiceWithCallback:^(EasyPeripheral *peripheral, NSArray<EasyService *> *serviceArray, NSError *error) {for (EasyService *tempS in serviceArray) {[tempS discoverCharacteristicWithCallback:^(NSArray<EasyCharacteristic *> *characteristics, NSError *error) {for (EasyCharacteristic *tempC in characteristics) {[tempC discoverDescriptorWithCallback:^(NSArray<EasyDescriptor *> *descriptorArray, NSError *error) {for (EasyDescriptor *desc in descriptorArray) {[desc readValueWithCallback:^(EasyDescriptor *descriptor, NSError *error) {}];}
queueMainStartEasyService *tempS = weakSelf.peripheral.serviceArray[0] ;EasyCharacteristic *tempC = tempS.characteristicArray[0];weakSelf.characteristic = tempC;NSLog(@"连上蓝 获取成功服务");
queueEnd}];}}];}}];
}

注意项:

写了一个NSMutableDictionary *foundDeviceDict如果不在扫描设备、已连接设备的集合中就加入其中,并通知外部调用者

之前通过NSArray来遍历数据,会存在偶现的闪退,定位后在这报错,直接遍历字典,因为key有时候返回的为nil
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
//字典直接enumerateKeysAndObjectsUsingBlock遍历数据[self.foundDeviceDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {if ([key isEqualToString:peripheral.identifier.UUIDString]) {EasyPeripheral *tempP = self.foundDeviceDict[key];tempP.deviceScanCount++ ;existedIndex = tempP.deviceScanCount ;*stop = YES;    }}];//发现一个设备的回调//去掉重复搜索到的设备}

绑定子设备的时候,已有不少麻烦的问题

  1. iOS的MAC地址和安卓的MAC的地址是不同的,倒叙的

  1. 部分子设备MAC地址需要自己手动截取一遍

由于系统限制,Android 上获取到的 deviceId 为设备 MAC 地址,iOS 上则为设备 uuid。因此 deviceId 不能硬编码到代码中。
[mac substringFromIndex:4]
NSString *macString = [NSString stringWithFormat:@"%@%@%@%@%@%@",[mac substringWithRange:NSMakeRange(10, 2)],[mac substringWithRange:NSMakeRange(8, 2)],[mac substringWithRange:NSMakeRange(6, 2)],[mac substringWithRange:NSMakeRange(4, 2)],[mac substringWithRange:NSMakeRange(2, 2)],[mac substringWithRange:NSMakeRange(0, 2)]];
mac = [mac substringWithRange:NSMakeRange(mac.length - 12, 12)];NSString *macString = [NSString stringWithFormat:@"%@%@%@%@%@%@",[mac substringWithRange:NSMakeRange(10, 2)],[mac substringWithRange:NSMakeRange(8, 2)],[mac substringWithRange:NSMakeRange(6, 2)],[mac substringWithRange:NSMakeRange(4, 2)],[mac substringWithRange:NSMakeRange(2, 2)],[mac substringWithRange:NSMakeRange(0, 2)]];

蓝牙产品在广播包中会以某个字节标识自己的类型,扫描到设备以后代理方法中会以字典的形式提供给我们。

iOS 8及以前kCBAdvDataManufacturerData这个数据提供的是scan response (SCAN_RSP),但是iOS 9及以后会把advertising packet (ADV_IND)scan response (SCAN_RSP)两部分合并在一起提供给了我们。所以不同版本的情况下我们获取kCBAdvDataManufacturerData会出现不同。

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI
{id data = advertisementData[@"kCBAdvDataManufacturerData"];
}

官方的问答https://www.jianshu.com/p/e9f647f59eb6

相关文章:

ios 通过搜索设备MAC地址绑定

最近做了一个物联网项目,涉及到了设备绑定配网这块,需要了解一下iOS BLE与设备绑定的相关知识点,第一次接触蓝牙相关的项目,所以开始熟悉蓝牙的相关信息。没有去深入研究BabyTooth库&#xff0c;只是感觉CoreBluetooth已经让我更好的理解整个流程这个物联网项目的设备绑定流程是…...

Python实现人脸识别,进行视频跟踪打码,羞羞的画面统统打上马赛克

哈喽兄弟们&#xff0c;我是轻松~ 今天我们来实现用Python自动对视频打马赛克前言准备工作代码实战效果展示最后前言 事情是这样的&#xff0c;昨天去表弟家&#xff0c;用了下他的电脑&#xff0c;不小心点到了他硬盘里隐藏的秘密&#xff0c;本来我只需要用几分钟电脑的&…...

vcf bed起始位置是0还是1

VCF 起始位置为1, POS - position: The reference position, with the 1st base having position 1. Positions are sorted numerically, in increasing order, within each reference sequence CHROM. It is permitted to have multiple records with the same POS. Telome…...

Hexo+live2d | 如何把live2d老婆放进自己的博客

参考&#xff1a;Hexo添加Live2D看板娘最新教程live2d-widgetlive2d-widget-models网页/博客Hexo添加live2d游戏角色看板娘,简易添加&#xff0c;碧蓝航线等live2d新型游戏角色模型&#xff08;moc3&#xff09;live2d-moc3jsdelivr方法1可以直接去看参考文章的第一部分的第一篇…...

【微信小程序】-- 页面导航 -- 导航传参(二十四)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…...

Pytorch学习笔记#2: 搭建神经网络训练MNIST手写数字数据集

学习自https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html 导入并预处理数据集 pytorch中数据导入和预处理主要用torch.utils.data.DataLoader 和 torch.utils.data.Dataset Dataset 存储样本及其相应的标签&#xff0c;DataLoader在数据上生成一个可迭…...

C语言 猜名次、猜凶手、杨辉三角题目详解

猜名次题目&#xff1a;5位运动员参加了10米台跳水比赛&#xff0c;有人让他们预测比赛结果&#xff1a;A选手说&#xff1a;B第二&#xff0c;我第三&#xff1b;B选手说&#xff1a;我第二&#xff0c;E第四&#xff1b;C选手说&#xff1a;我第一&#xff0c;D第二&#xff…...

蚁群算法负荷预测

%% 清空环境变量 clc clear close all format compact %% 网络结构建立 %% 清空环境变量 clc clear close all format compact %% 网络结构建立 %读取数据 dataxlsread(天气_电量_数据.xlsx,C12:J70);%前7列为每个时刻的发电量 最后列为天气 for i1:58 input(i,:)[data…...

ubuntu添加系统服务实现开机root权限运行

需求 开机自动运行程序(或脚本)&#xff0c;需要以root权限运行但不输入密码&#xff0c;也不能将密码写入文件。 环境 Ubuntu 20.04 解决方案 添加系统服务&#xff0c;然后通过systemctl控制。 操作步骤 假设目标程序为/home/xxx/test 1、创建service配置文件 [Unit…...

【阅读笔记】你不知道的Javascript--类与类型委托3

目录类一些常见原理混入行为委托委托理论类与对象更妙的设计与语法类型冷门关键词typeof 防范机制值原生函数访问内部属性类 一些常见原理 在继承或者实例化时&#xff0c;JavaScript 的对象机制并不会自动执行复制行为&#xff1b; 多态&#xff1a;JS 中的多态&#xff0c…...

文件服务设计

一、需求背景 文件的上传、下载功能是软件系统常见的功能&#xff0c;包括上传文件、下载文件、查看文件等。例如&#xff1a;电商系统中需要上传商品的图片、广告视频&#xff0c;办公系统中上传附件&#xff0c;社交类系统中上传用户头像等等。文件上传下载大致流程为&#…...

【批处理脚本】-1.22-字符串界定符号 ““

"><--点击返回「批处理BAT从入门到精通」总目录--> 共3页精讲(列举了所有字符串界定符号 ""的用法,图文并茂,通俗易懂) 在从事“嵌入式软件开发”和“Autosar工具开发软件”过程中,经常会在其集成开发环境IDE(CodeWarrior,S32K DS,Davinci,…...

【Flutter·学习实践·UI篇】基础且重要的UI知识

前言 参考学习官网&#xff1a;《Flutter实战第二版》 学习前先记住&#xff1a;Flutter 中万物皆为Widget&#xff0c;心中默念3次以上铭记于心。 这一点和开发语言Dart的变量一切皆是对象的概念&#xff0c;相互对应。 Widget 在前面的介绍中&#xff0c;我们知道在Flutt…...

【OpenCV】车牌自动识别算法的设计与实现

写目录一. &#x1f981; 设计任务说明1.1 主要设计内容1.1.1 设计并实现车牌自动识别算法&#xff0c;基本功能要求1.1.2 参考资料1.1.3 参考界面布局1.2 开发该系统软件环境及使用的技术说明1.3 开发计划二. &#x1f981; 系统设计2.1 功能分析2.1.1 车辆图像获取2.1.2 车牌…...

SpringBoot发送邮件

目录1. 获取授权码2. jar包引入3. 配置application4. 代码实现1. 获取授权码 以126邮箱为例&#xff0c;点开设置&#xff0c;选择POP3/SMTP/IMAP 开启POP3/SMTP服务&#xff0c;新增授权密码 扫码二维码&#xff0c;发送要求的短信内容到指定的号码即可&#xff0c;然后会返回…...

BigInteger类和BigDecimal类的简单介绍

文章目录&#x1f4d6;前言&#xff1a;&#x1f380;BigInteger类和BigDecimal类的由来&#x1f380;BigDecimal类的优点&#x1f380;BigDecimal类容易引发的错误&#x1f3c5;处理方法&#x1f4d6;前言&#xff1a; 本篇博客主要介绍BigInteger类和BigDecimal类的用途及常…...

mysql五种索引类型---实操版本

背景 最近学习了Mysql的索引&#xff0c;索引对于Mysql的高效运行是非常重要的&#xff0c;正确的使用索引可以大大的提高MySql的检索速度。通过索引可以大大的提升查询的速度。不过也会带来一些问题。比如会降低更新表的速度&#xff08;因为不但要把保存数据还要保存一下索引…...

【微信小程序】-- 页面导航 -- 编程式导航(二十三)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…...

路由追踪工具 traceroute 使用技巧

路由追踪工具 traceroute 使用技巧路由追踪工作原理路由追踪实例1. 如何运行 traceroute2. 禁用 IP 地址和主机名映射3. 配置回复等待时间4. 配置每一跳的查询次数5. 配置 TTL 值我想知道一个数据包从出发地到目的地所遵循的路由&#xff0c;即所有转发实体&#xff08;中间的路…...

NGINX学习笔记 - 一篇了解NGINX的基本概念(一)

NGINX是什么&#xff1f; NGINX是一款由俄罗斯人伊戈尔赛索耶夫使用C语言开发的、支持热部署的、轻量级的WEB服务器/反向代理服务器/电子邮件代理服务器&#xff0c;因为占用内存较少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;所以在互联网项目中广泛应用。可…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

鸿蒙HarmonyOS 5军旗小游戏实现指南

1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;采用DevEco Studio实现&#xff0c;包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...