# 智能门锁解决方案 感谢openharmony开源开发者成长计划所有的老师细心的辅导与教学,感谢成长计划的赋能。 **一.项目简介** 让用户通过数字管家实现开关门,更改密码和警告用户长时间未关门。 我上传的4个包的内容分别如下: 1.MQTT:适用于openharmony 3.0的MQTT协议。 2.门锁基础能力源码:基础的舵机开锁,上报订阅与下发与设备配网。 3.door test:实现功能化的门锁代码。 4.VS Code tool build:VS Code编译配置脚本 **二.编译方法&环境搭建** 1.环境搭建软件 操作系统:Ubuntu 编译构建工具:Python 包管理工具:HPM NPM环境:Node.js Openharmony源码版本:3.0 USB串口驱动:CH341SER.exe 烧录软件:Hiburn 开发板:润和HI3861 代码编辑工具:Visual Studio Code(DevEco Device Tool) 2.环境搭建 上述软件安装完成之后使用VS Code打开从码云获取的openharmony 3.0源码, 我们的项目开发主要路径在OpenHarmony/applications/sample/wifi-iot/app中进行。 配置VS Code的编译插件从我的码云仓库中获取工具。 **三.移植MQTT协议到鸿蒙3.0源码中&Dome实验** 从我的源码仓库中获取到MQTT协议后放到third party(第三方库)然后用润和给出的实验源码进行(注意这里润和官网提供的所有Dome都是基于openharmony的1.0源码的,所以在头文件吊起等都需要重做)。 ![基础原理](888888.jpg) ![基础原理](9999999.jpg) **四.智能门锁解决方案与代码结构** 1.用户操作界面:打开数字管家,点击开关锁按钮即可控制。用户可以在当前数字管家页面查看到门锁使用者管理以及云端下发的使用信息。详情如下图:![数字管家控制界面](%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220227193727.jpg) 2.设备实现原理: 设备:通过使用MQTT协议让设备连接上云端完成数据上报,订阅与下发。 交互流程:由智能门锁订阅的命令下发的主题经过代理服务器可下发到用户终端,用户终端就可收到通知。反之用户终端也可发送命令通过代理服务器到达智能门锁。 生命周期管理:对设备使用方的 RPC 对象进行管理,请求进行校验以及对更新后的进行回调处理。 ![门锁的结构](%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202022-02-27%20192808.jpg) * 无网解锁(总之,可以通过WIFI,局域网WIFI AP TCP,蓝牙发送固定码进行连接): 仅携带门禁卡:使用开发板上自带的NFC可以直接与手机NFC卡或实体门禁卡碰一碰解锁。仅针对于NFC识别,非正确门禁卡则指示灯闪烁,正确门禁卡则亮五秒钟。 * 通过手机:可以使用 WIFI TCP AP,或通过手机发送蓝牙固定码到服务端(门锁)。 WIFI TCP 实现:通过手机打开WIFI热点交换数据,建立一个TCP连接(给门禁锁进入一个新的局域网中)。 WIFI AP实现:通过AP搭建桥梁,使在服务端没有连接(断开)默认WIFI的时候起到中继作用。(相当于给信号不好的WIFI一个中继,不适宜在完全断网时使用) 蓝牙开锁实现:使用蓝牙芯片使智能锁和手机实现时间同步与密码文传输,将手机蓝牙固定码发送到智能锁中,从而不通过WIFI与NFC就可以将该智能锁进行打开。在初始化蓝牙模块后进行串口发送。 云端:首先去华为云平台创建产品与定义模型(获取IP与端口),然后获取上报和下发的通信数据,随后云平台就会给出设备ID与密钥。(后面会详细介绍) 下面是上发与订阅的解决方法: ``` //消息回调函数 void mqtt_callback(MessageData *msg_data) { size_t res_len = 0; uint8_t *response_buf = NULL; char topicname[45] = { "$crsp/" }; LOS_ASSERT(msg_data); printf("topic %.*s receive a message\r\n", msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data); printf("message is %.*s\r\n", msg_data->message->payloadlen, msg_data->message->payload); } int mqtt_connect(void) { int rc = 0; NetworkInit(&n); NetworkConnect(&n, "a161fa3144.iot-mqtts.cn-north-4.myhuaweicloud.com", 1883); buf_size = 4096+1024; onenet_mqtt_buf = (unsigned char *) malloc(buf_size); onenet_mqtt_readbuf = (unsigned char *) malloc(buf_size); if (!(onenet_mqtt_buf && onenet_mqtt_readbuf)) { printf("No memory for MQTT client buffer!"); return -2; } MQTTClientInit(&mq_client, &n, 1000, onenet_mqtt_buf, buf_size, onenet_mqtt_readbuf, buf_size); MQTTStartTask(&mq_client); data.keepAliveInterval = 30; data.cleansession = 1; data.clientID.cstring = "61f6e729de9933029be57672_88888888_0_0_2022020905"; data.username.cstring = "61f6e729de9933029be57672_88888888"; data.password.cstring = "43872acc0b1e6aa7bf9e6a69f12aa9b1ebc07daffb67e18cf905c847a594f813"; data.cleansession = 1; mq_client.defaultMessageHandler = mqtt_callback; //连接服务器 rc = MQTTConnect(&mq_client, &data); //订阅消息,并设置回调函数 MQTTSubscribe(&mq_client, "porsche", 0, mqtt_callback); while(1) { MQTTMessage message; message.qos = QOS1; message.retained = 0; message.payload = (void *)"openharmony"; message.payloadlen = strlen("openharmony"); //发送消息 if (MQTTPublish(&mq_client, "hi3861", &message) < 0) { printf("MQTTPublish faild !\r\n"); } IoTGpioSetOutputVal(9, 0); //9gpio 0 light on usleep(1000000); } return 0; } ``` ![云端连接成功](%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220228121602.jpg) 识别GPIO口与接入(这里要注意一个接的是正极一个是接地还有一个为信号传输口) ``` void mqtt_test(void) { IoTGpioInit(9); IoTGpioSetDir(9, IOT_GPIO_DIR_OUT); mqtt_connect(); } ``` 智能门锁可以通过舵机来实现开关锁 ``` int servoID =0; void My_servo(uint8_t servoID,int angle) { int j=0; int k=2000/200; angle = k*angle; for (j=0;j<5;j++){ IoTGpioSetOutputVal(servoID, 1); hi_udelay(angle); //angle ms IoTGpioSetOutputVal(servoID, 1); hi_udelay(20000-angle);// }//20ms } ``` 由于鸿蒙操作系统的临时问题导致不能达成鸿蒙的碰一碰配网,这里我等量代换成了开机后自动扫描并连接WIFI热点。 (问题会在下面的数字管家中详细介绍) ![设备成功连接手机热点](%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220227235924.jpg) ``` int hi_wifi_start_connect(void) { int ret; errno_t rc; hi_wifi_assoc_request assoc_req = {0}; /* copy SSID to assoc_req */ rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, "rui666", 8); /* 9:ssid length */ if (rc != EOK) { return -1; } //热点加密方式 assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK; /* 热点密码 */ memcpy(assoc_req.key, "88888888", 11); ret = hi_wifi_sta_connect(&assoc_req); if (ret != HISI_OK) { return -1; } return 0; } ``` * 由于成长计划在我的项目介绍中网页出错导致有一部分项目要求被隐去了(不管从手机端还是电脑端都无法看到那一部分,到结项的最后几天和小助手确认网页出问题了以后才知道)当时硬件购买后送到住址至少需要三天,后续还要进行代码结构与串口、驱动的调试,所以实在来不及了还请组委会的导师们见谅。(详细情况以反馈给小助手核实) 门未关的解决方案:通过锁芯的伸缩判断是否关门,或者添加红外传感器等传感扩展。 **五.云端配置与烧录到开发板** 1.云端:首先在华为云官方获取Client ID等身份识别信息,然后在云端的Topic中自定义订阅与发布。 ![自定义Topic](%E8%87%AA%E5%AE%9A%E4%B9%89topic.jpg) 在初次开发时可以使用MQTTX软件进行了命令的订阅与下发实验,显示在线成功接收到上报和订阅的消息 ![成功实验](%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220227220017.jpg) 这样华为云的配置就成功了 ![输入图片说明](%E8%AE%BE%E5%A4%87%E8%BF%9E%E6%8E%A5%E4%BA%91%E7%AB%AF%E6%88%90%E5%8A%9F.jpg) 如有需要还要进行产品定义与多功能的增加与实验。 2.编译:编译有两种方法 第一种是使用VS Code自带的编译功能(记得在里面配置并载入编译脚本): ![VS Code](%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202022-02-27%20195247.jpg) 点击build就可以生成json文件啦,编译成功后upload就可以直接烧录进去。(注意:在编译之后如果要再编译必须点击clean以删除build产生的json文件避免报错) 第二种方法是使用命令行进行编译:(注意:目前hb编译还不支持编译C++,编译的时候显示不认识) `hb set` //这是用于产生json文件的 `hb build` //这是用于编译的,编译后则会在源码的out文件夹中产生bin文件 `hb clean` //在build一次以后如果如果要再build那就必须进行此命令来删除json文件 在build成功后开发者就会发现在源码中的out文件夹中看到allinone.bin,然后发送到windows下使用Hiburn进行烧录即可(波特兰最大3000000,否则会烧坏板子) **六.通过Deveco studo数字管家的接入与吊起(部署与使用鸿蒙Abilit)下图为碰一碰卡片原理:** ![碰一碰卡片原理](111111111.png) 数字管家需要通过在APPGallery Connect中创建项目后添加应用从而获取Json文件,然后放在码云中下在的DistSchedule\netconfig\src\main\resources中。然后按照文档开发UI界面,点击构建的Generate Key and CSR创建用户名与密钥进行签名。 用户操作界面:在slice目录下新建 xxxSlice.java文件,通过addActionRoute方法为此AbilitySlice配置一条路由规则,并且在在应用配置文件(config.json)中注册。在resources/base/layout下新建对应xml布局文件,在上述两个文件中编写相应的UI。 数字管家数据处理:从slice获取deviceId:在onStart中通过调用DeviceID等,获取设备的名称等方便数字管家识别设备。从slice页面获取状态:开关锁可以直接调用intent.getBooleanParam来确定是进行开关锁还是对门锁的日程进行编排。 编写设备控制命令的解析:在CommandUtil中根据具体设备定义profile,来新增获取命令和解析命令的方法,用于设备在本地调用sendCommand来发送命令和解析。 配置设备端信息:在DeviceData的initData中,根据设备ProductID添加设备图片ID、跳转的action参数和解析方法,配置完成后设备列表页、用户页面等都能通过该配置进行图片加载、路由跳转和解析。 最后进行接口对接与NFC写入就可以了(通过应用调试助手写入NFC识别详细用于快速让手机识别到设备从而吊起数字管家实现鸿蒙的Ability) ![操作系统故障](HO.jpg) * 非常可惜的是遇到此情况向华为官方初步提交日志确认了由于开发者选项bug所以操作系统出现了问题,导致每次错误之后都会震动三下并生成错误报告,现已提交ZIP错误日志给官方进行进一步审查。情况已告知小助手并附上情况截图,希望在近期我的鸿蒙手机可以恢复与deveco studo的连接。 * 再回到NFC方面,已和厂家的硬件工程师确认我手上的NFC扩展板有不通电的问题。发现的时候因为项目距离结项只有三天所以来不及更换了导致此碰一碰配网与吊起被搁置。现已将我和厂家的聊天记录发给小助手核实过了,请组委会老师见谅。 **七.下面我会继续跟进此项目的开发,来充实openharmony生态。** This is moment, this is it and this is our time again, we must to take it back._