美文网首页iOS新手学习iOS BLE蓝牙学习
nRF芯片设备DFU升级(适配Xcode9.2)

nRF芯片设备DFU升级(适配Xcode9.2)

作者: zhangferry | 来源:发表于2016-12-15 16:47 被阅读3007次
Nordic.png

这里主要参考这个项目:iOS-nRF-Toolbox,它是Nordic公司开发的测试工程,包含一整套nRF设备的测试解决方案。

项目是用Swift写的,不过之前还是有OC版本的,但是后来由于一些**(不可描述的问题),才变成了现在的纯Swift版本。对于使用Swift开发的人员,直接仿照Demo操作即可。如果你是用Swift开发的,那下面的内容你可以不用看了。接下来我就讲一下针对OC引用DFU升级的操作步骤和我遇到的问题。

代码研究

nRF-Toolbox项目包含BGM,HRM,HTM,DFU等多个模块,我们今天只关注其中的DFU升级模块。打开项目,在对应的NORDFUViewController.swift中我们能够看到有三个引用库
import UIKit,import CoreBluetooth,import iOSDFULibrary,这里的iOSDFULibrary就是DFU升级的库,也是解决DFU升级最重要的组件。我们只要把这个库集成到我们的项目中,就能够完成nRF设备的DFU升级了。

集成步骤

有两种方案集成:

  • 通过cocoapods集成
  • 编译出framework然后把库导入项目

第一种方案是作者推荐的,但是我试了很久,引入DFULibrary会出现头文件找不到等一系列问题,无奈只能放弃,如果有人通过这种方式成功,还望告知。下面讲的是通过第二种方案的集成。

第一步:导出iOSDFULibrary

这一步是最关键也是最容易出问题的,这个库也是由Swift写成的,我们将这个库clone到本地,然后选择iOSDFULibrary进行编译

01.png

最后生成两个framework:

  • iOSDFULibrary.framework
  • Zip.framework

这时库内的代码已经变成了我们熟悉的OC语言。理论上这个库应该是没问题的了,但是事实还是有问题的,见issues#39。作者给出的解决方法是:

1、On your mac please install carthage (instructions)
2、Create a file named cartfile anywhere on your computer
3、add the following content to the file:

github "NordicSemiconductor/IOS-Pods-DFU-Library" ~> 2.1.2
github "marmelroy/Zip" ~> 0.6

1、Open a new terminal and cd to the directory where the file is
2、Enter the command carthage update --platform iOS
3、Carthage will now take care of building your frameworks, the produced .framework files will be found in a newly created directory called Carthage/Build/iOS,copy over iOSDFULibrary.framework and Zip.framework to your project and you are good to go.

carthage是一种和cocoapods相似的的类库管理工具,如果不会使用的话可以参照Demo,将framework文件导入到自己的项目。

第二步、导入framework
Target->General

128F494E-C863-49E7-AC44-A7B53B3EB463.png

直接拖入项目默认只会导入到Linked Frameworks and Libraries,我们还需要在Embeded Binaries中引入。

第三步、使用iOSDFULibrary

//create a DFUFirmware object using a NSURL to a Distribution Packer(ZIP)
DFUFirmware *selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:url];// or
//Use the DFUServiceInitializer to initialize the DFU process.
DFUServiceInitiator *initiator = [[DFUServiceInitiator alloc] initWithCentralManager: centralManager target:selectedPeripheral];
[initiator withFirmware:selectedFirmware];
// Optional:
// initiator.forceDfu = YES/NO; // default NO
// initiator.packetReceiptNotificationParameter = N; // default is 12
initiator.logger = self; // - to get log info
initiator.delegate = self; // - to be informed about current state and errors 
initiator.progressDelegate = self; // - to show progress bar
// initiator.peripheralSelector = ... // the default selector is used

 DFUServiceController *controller = [initiator start];

库中有三个代理方法DFUProgressDelegateDFUServiceDelegateLoggerDelegate,它们的作用分别为监视DFU升级进度,DFU升级及蓝牙连接状态,打印状态日志。

常见问题

1、selectedFirmware返回nil

DFUFirmware *selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:url];

需要在GeneralEmbeded Binaries选项卡里导入那Zip.frameworkiOSDFULibrary.framework
2、崩溃报错

dyld: Library not loaded: @rpath/libswiftCore.dylibReferenced from: /private/var/containers/Bundle/Application/02516D79-BB30-4278-81B8-3F86BF2AE2A7/XingtelBLE.app/Frameworks/iOSDFULibrary.framework/iOSDFULibraryReason: image not found

需要改两个地方


error1.png erro2.png
如果不起作用,将Runpath Search Paths的选项内容删掉再重新添加一遍即可
3、打包上架时报ERROR IT MS-90087等问题
问题描述:
ERROR ITMS-90087: "Unsupported Architectures. The executable for ***.app/Frameworks/SDK.framework contains unsupported architectures '[x86_64, i386]'."
ERROR ITMS-90362: "Invalid Info.plist value. The value for the key 'MinimumOSVersion' in bundle ***.app/Frameworks/SDK.framework is invalid. The minimum value is 8.0"
ERROR ITMS-90209: "Invalid Segment Alignment. The app binary at '***.app/Frameworks/SDK.framework/SDK' does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."
ERROR ITMS-90125: "The binary is invalid. The encryption info in the LC_ENCRYPTION_INFO load command is either missing or invalid, or the binary is already encrypted. This binary does not seem to have been built with Apple's linker."

解决方法,添加Run Script Phase

error3.png

Shell脚本内容填写如下内容,再次编译即可

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done

完整OC项目

这个是对应Swift版本用OC写的完整项目,应该是OC停止维护之前的版本。会有一些bug。在将DFUFramework更新之后,我把它搬到了我的github上,有需要的同学可以下载研究:OC-nRFTool-box


以下为更新内容,时间:2017.12.26
收到很多关于无法适配Xcode9.2的反馈,因为最近比较忙没时间处理,不好意思啦,今天抽出时间来把代码更新了一下。

Xcode9.2 出现的问题

1、dyld: Library not loaded: @rpath/libswiftCore.dylib
Referenced from: /private/var/containers/Bundle/Application/02516D79-BB30-4278-81B8-3F86BF2AE2A7/XingtelBLE.app/Frameworks/iOSDFULibrary.framework/iOSDFULibrary
Reason: image not found
2、DFUFirmware *selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:url]; 返回为空或者崩溃问题

我的测试结果是更新iOSDFULibrary. framework和Zip.framework可以解决以上问题。

解决方案 Carthage

因为这两个库都是通过Swift维护的,所以更新framework最好还是要用适用Swift的方式,包括以后的更新也一样。所以我推荐用Carthage更新这俩库,下面是使用Carthage的简单介绍,详细的可以看这里Carthage的安装和使用
另外OC-nRFTool-box也已经更新,里面的Framework可以直接拿来用。

1、安装brew

 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2、brew更新

brew update

3、安装Carthage

brew install carthage

4、使用Carthage

cd ~/路径/项目文件夹 /**进入项目文件夹下*/
touch Cartfile /**创建carthage文件*/
open Cartfile /**打开carthage文件*/
/**输入以下内容*/
github "NordicSemiconductor/IOS-Pods-DFU-Library" ~> 4.1
github "marmelroy/Zip" ~> 1.1

5、运行Carthage

carthage update --platform iOS /**编译出iOS版本*/

6、更新framework

cd Carthage/Build/iOS  /**framework输出位置,将老的framework替换掉*/

注意
nRF Toolbox项目方法变更

[initiator withFirmwareFile:selectedFirmware];/** 旧版本方法 */
initiator = [initiator withFirmware:selectedFirmware];/** 新版本方法 */

相关文章

网友评论

  • 大海中的海绵:你们知道为什么项目选择Resease模式就报dyld: Library not loaded: @rpath/libswiftCore.dylibReferenced from: /private/var/containers/Bundle/Application/02516D79-BB30-4278-81B8-3F86BF2AE2A7/XingtelBLE.app/Frameworks/iOSDFULibrary.framework/iOSDFULibraryReason: image not found
    问题
    大海中的海绵:@阿福lfy 我试了不是这个问题
    阿福lfy:targets- Build Phases - Link Binary With Libraries 找到iOSDFULibrary.framework,设置为:Optional,试试吧!
    1733b346f21f:我这边是xcode10编译出的问题,用的是作者demo中的framework,现在自己用Carthage编译的最新的github "NordicSemiconductor/IOS-Pods-DFU-Library" ~> 4.1.3
    github "marmelroy/Zip" ~> 1.1.0编译ok了,不知这能不能帮到你
  • VVik:感谢分享。因为公司的工程都是旧的项目(OC),我也不想混编,毕竟纯的一种语言才是高效率。因此我会持续关注您的OC 固件升级那份。:+1:
    VVik:发现还是swift库。他们原本都没有oc编写的库么?
  • 堇之:显示Scanning for the DFU Bootloader...之后没了。这是什么问题
  • bcb155e2ef24:大神,我报错Error 302: DFU Service not found 库是最新的,方法也是你这样的。可以帮我分分析吗?
    iOSTbag:@bcb155e2ef24 解决了么 兄弟 我也遇到了。 请关照
    bcb155e2ef24:@勇闯天涯茉莉花茶 我用pod导入跟你遇到了一样的问题,就是头文件找不到。
    zhangferry:可以用pod导入DFU的库试试
  • Gizone_iac:Hi 勇闯天涯茉莉花茶,

    请问升级完成后,外设由DFU变回正常模式,没有触发我的Disconnect 同时也没办法重新连接到设备。请问有什么解决方案吗?
  • 19af449ade54:你好 Xcode9.3 运行就报错 dyld: Library not loaded: @rpath/iOSDFULibrary.framework/iOSDFULibrary
    Referenced from: /Users/lidz/Library/Developer/CoreSimulator/Devices/F45DF16D-E156-4F07-B785-186AEC36C751/data/Containers/Bundle/Application/4AEE5E8A-58E6-4D9B-8BAA-51310DBCA8C4/BlueThooth.app/BlueThooth
    Reason: image not found 是不是因为没有最新的库呢?能不能发一下最新的库呀 麻烦大佬加我一下QQ 351370338 非常感谢
    zhangferry:@李德争 这个问题一般都是iOSDFULibrary.framework版本引起的,可以用carthage编译一下,导出替换原有的包,这个是包的地址https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library
  • 胡伟红:你好,如果用这个库的话,是不是手机系统是9.3的就不能升级了?
    胡伟红:@勇闯天涯茉莉花茶 好的,我看看,修改一下,有问题继续沟通
    zhangferry:@胡伟红 不是啊,适配的是Xcode版本,不是手机系统版本。手机系统版本应该是不受限制的,具体可以查看nRF官网
  • printHello:你好,请问一下我也是用的iOSDFULibrary进行dfu升级 升级成功了以后app就搜索不到周边设备了,必须关闭app重新启动才能搜索到 是什么原因呢
    海泉:@bcb155e2ef24
    Centermanager 被iOSDFULibrary持有了。
    bcb155e2ef24:你的这个问题解决了吗?Error 302: DFU Service not found 我也是这个问题。
  • 9d3354a7ec42:dyld: Library not loaded: @rpath/libswiftCore.dylib
    Referenced from: /private/var/containers/Bundle/Application/4DFFAF42-9D5D-44BB-B1A9-A514CD3C7361/固件升级demo.app/Frameworks/Zip.framework/Zip
    Reason: image not found 动态库是从你的github下的最新的,也按照文章操作了,模拟器可以跑,真机跑就报这个错误了。
  • 一点东风:为啥一直给我报错Error 302: DFU Service not found,但是程序是起来的,而且设备也进入升级状态了
    一点东风:@bcb155e2ef24 写升级包的时候必须断开设备
    一点东风:@bcb155e2ef24 解决了
    bcb155e2ef24:兄弟你这个问题解决了吗?
  • 40a803087ce1:更新之后,方法也修改了。现在demo可以运行了。非常感谢。
  • 萌萌萌萌萌萌吗:#pragma mark - 当设备连接成功时调用此代理方法
    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
    //连接成功
    NSLog(@"%@连接成功了",peripheral.name);
    //开始更新
    DFUServiceInitiator *initiator = [[DFUServiceInitiator alloc]initWithCentralManager:_manager target:peripheral];
    initiator.logger = self;
    initiator.forceDfu = NO;
    initiator.packetReceiptNotificationParameter = 12;
    initiator.delegate = self;
    initiator.progressDelegate = self;
    [initiator onPeripheralDFUDiscovery:YES];
    self.selectedFirmware = [[DFUFirmware alloc]initWithUrlToZipFile:self.myURlString];
    self.dfuController = [[initiator withFirmwareFile:self.selectedFirmware] start];
    }
    我的方法是这样写的 ,但是为什么一点作用都没有,都没有打印信息
    zhangferry:@萌萌萌萌萌萌吗 路径不为空不代表就能初始化成功,以DFUServiceInitiator对象的实例化为准。检测硬件升级,在nRFToolBox测试。关于升级流程可以参考[蓝牙固件升级](https://www.jianshu.com/p/0d956862ffa1)。
    萌萌萌萌萌萌吗:@勇闯天涯茉莉花茶 我检查过了我的文件路径 是不为空 一般正常的情况不应该是连接Update 成功后就进行升级吗 或者是应该在那个地方触发这段代码比较好呢
    zhangferry:@萌萌萌萌萌萌吗 首先检查self.selectedFirmware是否为空。
    另外, 每个硬件的升级过程都有差别,一般是要向硬件发送升级指令,待硬件准备好之后再进行升级操作。连接成功就进行升级,我没遇见过这种情况,也有可能是这个触发时机的问题。
  • Sam_xing:dyld: Library not loaded: @rpath/libswiftCore.dylib
    Referenced from: /private/var/containers/Bundle/Application/02516D79-BB30-4278-81B8-3F86BF2AE2A7/XingtelBLE.app/Frameworks/iOSDFULibrary.framework/iOSDFULibrary
    Reason: image not found

    按照你的方法还是一样的报错.这是为什么?
    zhangferry:文章已经更新,可以解决这个问题
  • Sam129:你好,我是用cocoapods集成它的,项目还是用的OC,调用起来没有什么问题。只是有一点,手机会对连接过的BLE设备的Services进行缓存,若设备升级后Services等有改动,比如service的个数发送变化了。此时就得刷新缓存,否则扫到的服务值始终只有一个,但是刷新缓存的方法并没有开放,只有重启蓝牙后才可以搜到其他服务。安卓的可以使用反射来调用BluetoothGatt类中的refresh()方法,但是苹果的怎么处理呢?
  • 105d53922025:你好,请问一下我也是用的iOSDFULibrary进行dfu升级 升级成功了以后app就搜索不到周边设备了,必须关闭app重新启动才能搜索到 是什么原因呢
    printHello:大佬,您是怎么解决的,我也遇到这问题
  • wokenshin:额,大神可以更新一下文章。这个库已经改过了。还有就是我没有学过Swift,现在打算用混编的方式去调用这个库。简单的 自己写的Swift 还知道怎么用OC去调用。可复杂一些的。就不套清楚了
  • 逸风lovely:您好!请问一下,现在用DFUFirmware *selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:url]创建对象会崩溃了,以前是没有,然后用您的demo打开升级文件也崩溃在这。以前没有这个情况,最近出现的。
    逸风lovely:@陌颜微笑 你用DFUServiceController去接一下[initiator start]看看,它也有代理方法可以看到升级的状态及进度的。也可以控制升级的状态
    235a008fb19c:你好 就是调用[initiator start];后 didStateChangedTo的状态一直是0(DFUStateConnecting),根本就没有进行DFUStateStarting DFUStateUploading这两个状态 你觉得问题会出现在哪呢?
    zhangferry:@逸风lovely 我还没升级,等升级之后测一下你说的问题。
  • 9b4792ecc955:这个第一步是怎么生成的,能详细写一下么,谢谢
    玉门山海关:selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:url];
    你好,你的demo和官方的demo都崩到这段代码上了,我是更新到xcode8.3才出现这个问题的,请问这是怎么回事呢
    9b4792ecc955:@勇闯天涯茉莉花茶 哦,好的,谢谢
    zhangferry:不会用carthage的话可以下载我的示例项目,把那两个framework拖出来
  • IT民工高先生:这方面的东西太少了,你这算是最有用的了。我问一下问什么我直接崩溃到main函数了,能不能指导一下。
    IT民工高先生:@勇闯天涯茉莉花茶 我是核对了一下其他配置,还是没有找到原因,崩到main函数堆栈信息也看不出来原因,所以不知道是不是哪里出了问题。要导入的就只有IOSDFULibrary和Zip两个framework吧,方便的话私信
    zhangferry:遇到崩溃的问题应该首先检查一下工程的配置环境,然后根据错误提示确认问题
  • 61bc2b09ad9b:您好,请问我使用DFUFirmware *selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:url];创建selectedFirmware对象时返回为null,是什么原因,url没有问题,用你的demo试了url也是同样没有问题的
    zhangferry:@yanzihui_218 问题解决方法已经补充到正文了,你看一下
    61bc2b09ad9b:dyld: Library not loaded: @rpath/libswiftCore.dylib
    Referenced from: /private/var/containers/Bundle/Application/02516D79-BB30-4278-81B8-3F86BF2AE2A7/XingtelBLE.app/Frameworks/iOSDFULibrary.framework/iOSDFULibrary
    Reason: image not found 操作之后就崩了,我把framework都改成optional了呀
    zhangferry:@yanzihui_218 要在Embeded Binaries选项卡里添加那两个库文件

本文标题:nRF芯片设备DFU升级(适配Xcode9.2)

本文链接:https://www.haomeiwen.com/subject/sflgmttx.html