产品需求
GZ3 是本公司开发的第二款网关设备,是一款轻量型的符合 Zigbee 3.0 的智能家居网关,其操作简单、配置方便,支持 ZHA 协议、ZLL 协议等符合 Zigbee 3.0 标准的智能无线连接、自由组网,供强大的无线监控和远程控制功能。
功能描述
根据之前的开发基础和市场需求综合考虑,本网关必须支持以下部分或全部功能:
以太网接口,可以支持局域网或者广域网访问;
Zigbee(3.0),支持组网控制灯具或其他 Zigbee 设备;
支持远程升级和 APP 局域网内升级固件(包括网关和协调器);
多个指示灯,分别指示局域网、广域网已经网关的工作状态等;
支持硬件复位和软、硬件恢复出厂设置;
大容量的网关数据存储功能。
屏幕快照 2017-04-26 下午12.39.48.png 屏幕快照 2017-04-26 下午12.40.02.png
软件控制部分
GZ3是基于局域网和远程控制的中断转发控制设备,可以通过局域网或者远程服务器的访问的 方式与用户手机、平板等智能终端控制设备进行无线连接。
屏幕快照 2017-04-26 下午12.41.06.png
AduroSmarkSDK 详解
为了更好的区分程序功能模块和减少代码结构,故考虑将整个通讯以及数据交互解析的工作放在了SDK中来处理,极大程度的提高了开发效率。基于上面的软件框图,建立了局域网的UDP 通讯 和 广域网的MQTT 通讯,后期扩展TCP通讯都包含在了其中,主要难点是我们的服务器在国外,客户大多在欧美,网络切换的判断(wifi 局域网 4g )断线重连等。具体不在啰嗦,一切都在代码中。
整体代码结构:
屏幕快照 2017-04-26 下午3.08.01.png建议各种指令枚举搞定
屏幕快照 2017-04-26 下午3.10.33.png局域网控制效果
屏幕快照 2017-04-26 下午3.15.05.png切换网络自动监测成功率99.99%
屏幕快照 2017-04-26 下午7.05.00.png顺带做了下TCP相关操作,心跳连接,掉线重连,后台断开,等操作。
屏幕快照 2017-04-26 下午3.21.19.png本来没想到打包使用,但同事要求就做了打包操作,打包流程如下:
如果你想将你开发的控件与别人分享,一种方法是直接提供源代码文件。然而,这种方法并不是很优雅。它会暴露所有的实现细节,而这些实现你可能并不想开源出来。此外,开发者也可能并不想看到你的所有代码,因为他们可能仅仅希望将你的这份漂亮代码的一部分植入自己的应用中。
另一种方法是将你的代码编译成静态库(library),让其他开发者添加到自己的项目中。然而,这需要你一并公布所有的公开的头文件,实在是非常不方便。
你需要一种简单的方法来编译你的代码,这种方法应该使得你的代码易分享,并且在多个工程中易复用。你需要的是一种方法来打包你的静态库,将所有的头文件放到一个单元中,这样你就可以立刻将其加入到你的项目中并使用。
OS X完美地支持这一点,因为Xcode就提供了一个项目模板,包含着默认构建目标(target)和可以容纳类似于图片、声音、字体等资源的文件。你可以为 iOS创建Framework,不过这是一个比较复杂的手工活,如果你跟着教程走,你将学到怎么样跨过路障,顺利地完成Framework的创建。
1440398-d9bc370b5d9d4e9e.png我们可以看出.a的封装和.framework的封装差不多,也有模拟器和真机合并的过程,通过上边的图片我们可以看出.a 和.framework的区别,就是.a+.h+soureFile=.framework。可以看出我们直接封装.framework其实是最好的。那 么我们就来看看framework怎么封装的。
步骤一
1440398-596575a27c2dbb12.png步骤二 在TARGETS下选中工程,在Build Settings下更改几个参数。
1440398-df57a4870204e50a.png步骤三 在Architectures下增加armv7s,并选中。将Build Active Architecture Only 设置为NO。
1440398-da1cdc8a7a98f7f6.png步骤四设置Headers 将你要公开的头文件拖至Public下,要隐藏的放在Private或者Project下,当然,隐藏的头文件就无法再被引用。如果程序用了category 要在导入时候 other link 中加入 -Objc -all_load
屏幕快照 2017-04-26 下午7.28.52.png公开头文件
屏幕快照 2017-04-26 下午7.32.41.png步骤五 简易打包方法
- 选中TARGETS下的工程,点击上方的Editor,选择Add Target创建一个Aggregate.
2、选择Other下的Aggregate,点击Next创建。
1440398-5d7af944c9a95861.png3、嵌入脚本。选中刚刚创建的Aggregate,然后选中右侧的Build Phases,点击左下方加号,选择New Run Script Phase
#Sets the target folders and the finalframework product.
#如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME
#例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}
#Install dir will be the final output tothe framework.
#The following line create it in the rootfolder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
#Working dir will be deleted after theframework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
#-configuration ${CONFIGURATION}
#Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [-d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binaryfiles (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${INSTALL_DIR}"
4、编译。如图所示,command+B编译。这里Generic iOS Device的意思是“iOS通用设备”,大概就是说模拟器和真机都能用。
1440398-8caff1134f18f347.png5、编译成功后会自动跳出一个finder,保存这个.framework,这就是我们需要的framework。
屏幕快照 2017-04-26 下午7.44.55.png6.然后就可以随便用了
7.注意
2、开始打包的时候,一定要在选中模拟器和选中真机上边分别编译一次, 我觉得之前在家里没有真机的时候编译的好像不对。
3、在终端上边合并的时候可能是error并生成一个.lipo文件,不要怕,大胆修改成同名的不挂后缀的同名文件。
4、调用的时候分清楚是类方法还是实例方法,方便调用。
5、在制作framework或者lib的时候,如果使用了category,则使用改FMWK的程序运行时会crash,此时需要在该工程中 other linker flags添加两个参数 -ObjC -all_load。(这点没有亲测)
6、带有图片资源的需要把图片打包成Bundle文件,和framework一起拷贝到相应的项目中。
7、公开的类中如果引用的private的类,打包以后对外会报错,找不到那个private的类,可以把那个private的.h放到(也没亲测)
8、**namespace 冲突。**静态库用了某第三方库,项目也用了同样的第三方库,在编译的时候就会有 duplicate symbol 错误,因为有两份同样的第三方库。解决办法就是把用到的第三方库加上自定义前缀,包括类名、delegate 协议、常量名,尤其需要注意 Category 的方法名要修改。
9、封装静态库的时候应尽量避免引入重量级第三方库,**多自己进行封装**。
10、一个静态库要**有自己独有的前缀**,所有类名、常量等都要加同样的前缀。
11、**真机+模拟器支持**。(和第2条意思一样)Xcode 默认只会用当前环境(真机或模拟器)生成静态库,这样的 SDK 不方便其他项目开发时调试。解决办法就是通过脚本生成一份通用库,build_universal_library.sh,via SO.
12、**文档**。静态库的方便是使用者直接拿你提供的方法来用,无需关注具体实现;不方便在于看不到实现,出现问题无法排查,因此需要把 SDK 的版本、更新历史、使用、FAQ 等写成文档,方便使用,也显得 SDK 比较正式规范。
13、图片等资源文件用** bundle **方式打包。一个简单制作 bundle 的方法:新建文件夹,重命名为 YourSDK.bundle,然后 Show Package Contents 打开,加入图片。使用图片的时候需要指明 bundle: [UIImage imageNamed:@"YourSDK.bundle/img.png"]。也可以用 Target 方式制作 bundle,比如 iOS Library With Resources[http://www.galloway.me.uk/tutorials/ios-library-with-resources/](http://www.galloway.me.uk/tutorials/ios-library-with-resources/).
14、如果 SDK 有用到** Category**,注意项目设置 Other Linker Flags 添加 -ObjC。(后边介绍了-ObjC的作用)```
8.补充
从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件
在 最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许 多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文 件。Other linker flags设置的值实际上就是ld命令执行时后面所加的参数
下面逐个介绍3个常用参数:
-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中
-all_load:会 让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有 可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。
-force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载
网友评论