小车控制由MQTT控制,有简单有复杂按钮控制有简单有复杂#开发板漂移方案#小车控制有简单有UDP控制复杂本文是在前两篇帖子的基础上,实现了小车自动Openharmony3.0上电后连接指定WIFI,与指定MQTTBroker通信建立链接,订阅车控主题“carControl”。在电脑Windows系统下,使用paho软件连接同一个MQTTBroker,通过发送主题为“carControl”的消息来控制汽车的状态。阅读本文前,推荐阅读连志安老师的以下文章:MQTT协议开发简介-MQTT简介、设计规范、主要特点、协议原理、协议报文结构HowtotransplantPaho-MQTTinHarmonyOSopenharmony1。0移植Paho-MQTT教程在鸿蒙系统上使用MQTT编程-对应连老师Gitee仓库harmony_mqtt的使用介绍,本文基于此版本实现MQTT控制小车,并实现demoMQTT控制车。2.在Ubuntu20.04虚拟机上安装mosquitto搭建Broker。安装前,请确保您的Ubuntu可以正常上网,并且可以在本地网络访问。2.1在Ubuntu下安装mosquitto。安装说明如下:sudoapt-getinstallmosquittosudoapt-getinstallmosquitto-clientssudoapt-getinstallmosquitto-dev2.2安装完成后可以使用如下命令查看servicemosquittostatus的状态。地址为你Ubuntu局域网中的IP,端口默认为1883,如果搭建有什么问题欢迎留言交流。3、如何在Openharmony3.0上使用harmony_mqtt3.1使harmony_mqtt编译成功3.1.1下载harmony_mqtt到Openharmony3.0源码的third_party目录下,重命名为pahomqtt。可以用gitclone下载并重命名,也可以下载压缩包解压。Z:\ohos300_iot\是我Openharmony3.0源码的根目录如下图3.1.2hispark_pegasus中添加pahomqtt编译修改device\hisilicon\hispark_pegasus\sdk_liteos\BUILD.gnlite_component中添加"//third_party"("sdk")/pahomqtt:pahomqtt_static"(注:这里修改的BUILD.gn与Openharmony1.0版本不同,1.0路径为vendor\hisi\hi3861\hi3861\BUILD.gn)lite_component("sdk"){features=[]deps=["//build/lite/config/component/cJSON:cjson_static","//device/hisilicon/hispark_pegasus/hi3861_adapter/kal","//third_party/pahomqtt:pahomqtt_static",]}重新执行修改后编译之后可以使用mqtt从编译日志中查看日志,如果修改成功会显示如下信息。但是编译结束的时候会出现如下错误信息,并且下一步是修复此编译错误。3.1.3修改错误错误日志截取如下[OHOSERROR]riscv32-unknown-elf-ld:ohos/libs/libpahomqtt_static.a(libpahomqtt_static.MQTTLiteOS.o):infunction`MutexInit':[OHOSERROR]MQTTLiteOS.c:(.text.MutexInit+0x0):multipledefinitionof`MutexInit';ohos/libs/libdiscovery.a(libdiscovery.os_adapter.o):os_adapter.c:(.text.MutexInit+0x0):firstdefinedhere[OHOSERROR]riscv32-unknown-elf-ld:ohos/libs/libpahomqtt_static.a(libpahomqtt_static.MQTTLiteOS.o):infunction`MutexLock':[OHOSERROR]MQTTLiteOS.c:(.text.MutexLock+0x0):multipledefinitionof`MutexLock';ohos/libs/libdiscovery.a(libdiscovery.os_adapter.o):os_adapter.c:(.text.MutexLock+0x0):firstdefinedhere[OHOSERROR]riscv32-unknown-elf-ld:ohos/libs/libpahomqtt_static.a(libpahomqtt_static.MQTTLiteOS.o):infunction`MutexUnlock':[OHOSERROR]MQTTLiteOS.c:(.text.MutexUnlock+0x0):multipledefinitionof`MutexUnlock';ohos/libs/libdiscovery.a(libdiscovery.os_adapter.o):os_adapter.c:(.text.MutexUnlock+0x0):firstdefinedhere[OHOSERROR]scons:***[输出/bin/Hi3861_wifiiot_app.out]Error1[OHOSERROR]BUILDFAILED!!!![OHOSERROR]Failedbuildingoutput/bin/Hi3861_wifiiot_app.out:Error1[OHOSERROR]youcancheckbuildlogin/home/soon/ohos300_iot/out/hispark_pegasus/wifiiod_logincommand:"/home/soon/ohostool_101/ninja/ninja-wdupbuild=warn-C/home/soon/ohos300_iot/out/hispark_pegasus/wifiiot_hispark_pegasus"失败[OHOSERROR]返回码:1[OHOSERROR]执行路径:/home/soon/iotsoon0@soon-u20:~/ohos300_iot$我的修改方法是third_party\pahomqtt\MQTTClient-C\src\MQTTClient.ctird_party\pahomqtt\MQTTClient-C\src\liteOS\MQTTLiteOS.chthird_party\pahomqtt\MQTTClient-C\srcAllMutexInit(Mutex*);MutexLock\liteOS\MQTTLiteOS.h这三个文件中的(Mutex*);MutexUnlock(Mutex*)应该替换为MqttMutexInit(Mutex*);MqttMutexLock(Mutex*);MqttMutexUnlock(Mutex*);这样就可以正常编译通过3.1.4third_party\pahomqtt\BUILD.gn中的其他修改和修改代码下面三个不会影响编译/使用,所以我去掉了他"MQTTClient-C\src\liteOS","//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include","//kernel/liteos_m/components/cmsis/2.0",修改后的代码可以直接下载附件下载或从码云https://gitee.com/soonliao/pahomqtt下载。3.2MQTT控制小车代码实现3.2.1修改applications\sample\wifi-iot\app\car_mqtt\BUILD.gn在application的BUILD.gn中添加如下三行调用pahomqttstatic_library("car_mqtt"){sources=[...]include_dirs=[..."//third_party/pahomqtt:pahomqtt_static","//third_party/pahomqtt/MQTTPacket/src","//third_party/pahomqtt/MQTTClient-C/src",]}3.2.2MQTT初始化主题订阅主要实现在以下几个函数中。详细说明参考鸿蒙系统MQTT编程#include"MQTTClient.h"#defineMQTT_BROKER"192.168.123.230"//改成你的MQTTBroker地址#defineMQTT_PORT1883MQTTMessageackmsg;intneedAck=0;structopts_struct{char*clientid;intnodelimiter;char*定界符;enumQoSqos;char*用户名;char*密码;char*主机;intport;intshowtopics;}opts={(char*)"stdout-subscriber",0,(char*)"\n",QOS2,NULL,NULL,(char*)MQTT_BROKER,MQTT_PORT,1};unsignedcharbuf[100];unsignedcharreadbuf[100];intcar_mqtt(void){intrc=0;MQTTMessagepubmsg;//车控topiccarControlchar*topic="carControl";if(strchr(话题,'#')||strchr(topic,'+'))opts.showtopics=1;if(opts.showtopics)printf("topicis%s\n",topic);Networkn;MQTTClientc;//网络初始化NetworkInit(&n);NetworkConnect(&n,opts.host,opts.port);//设置MQTT缓存并启动MQTT线程MQTTClientInit(&c,&n,1000,buf,100,readbuf,100);MQTTStartTask(&c);//设置MQTT相关参数MQTTPacket_connectDatadata=MQTTPacket_connectData_initializer;data.willFlag=0;data.MQTTVersion=3;data.clientID.cstring=opts.clientid;data.username.cstring=opts.username;data.password.cstring=opts.password;data.keepAliveInterval=10;data.cleansession=1;printf("Connectingto%s%d\n",opts.host,opts.port);//连接到MQTT服务器rc=MQTTConnect(&c,&data);printf("Connected%d\n",rc);//订阅主题并接收消息printf("订阅%s\n",topic);rc=MQTTSubscribe(&c,topic,opts.qos,messageArrived);printf("订阅%d\n",rc);//状态变化后发布主题carStatus,消息内容ackmsg.payloadmemset(&ackmsg,'\0',sizeof(ackmsg));ackmsg.payload=(void*)"ACK";ackmsg.payloadlen=strlen((char*)ackmsg.payload);ackmsg.qos=QOS0;ackmsg.retained=0;ackmsg.dup=0;while(1){if(needAck==1)//收到消息后,发送主题carStatus并携带状态消息{needAck=0;printf("PublishcarStatusackmsg%d%s\n",(int)ackmsg.payloadlen,(char*)ackmsg.payload);MQTTPublish(&c,"carStatus",&ackmsg);}sleep(1);}printf("Stopping\n");MQTTDisconnect(&c);NetworkDisconnect(&n);return0;}3.2.1通过MQTTSubscribe(&c,topic,opts.qos,messageArrived)进行车控代码;注册messageArrived回调实现,代码如下=0;确认消息。dup=0;if(opts.showtopics)printf("%.*s\t",md->topicName->lenstring.len,md->topicName->lenstring.data);if(opts.nodelimiter)printf("%.*s\n",(int)message->payloadlen,(char*)message->payload);elseprintf("%.*s%s\n",(int)message->payloadlen,(char*)消息->有效载荷,opts.delimiter);if(strncmp("forward",message->payload,7)==0){needAck=1;car_go_forward();ackmsg.payload=(void*)"forward";}if(strncmp("back",message->payload,4)==0){needAck=1;car_go_back();ackmsg.payload=(void*)"back";}if(strncmp("left",message->payload,4)==0){needAck=1;car_turn_left();ackmsg.payload=(void*)"left";}if(strncmp("right",message->payload,5)==0){needAck=1;car_turn_right();ackmsg.payload=(void*)"right";}if(strncmp("stop",message->payload,4)==0){needAck=1;car_stop();ackmsg.payload=(void*)"stop";}if(needAck==1){ackmsg.payloadlen=strlen((char*)ackmsg.payload);}}4.编译测试4.1小车控制代码编译请参考附件或Giteehttps完整代码://gitee.com/soonliao/car_mqtt,使用方法如下4.1.1将car_mqtt解压或gitclone到applications\sample\wifi-iot\app\路径下4.1.2修改applications\sample\wifi-iot\app\BUILD.gnimport("//build/lite/config/component/lite_component.gni")lite_component("app"){features=["car_mqtt",]}4.1.3修改WIFISSID、密码和MQTTBrokerIP修改applications\sample\wifi-iot\app\car_mqtt\src\car_main.c#defineWIFI_SSID"SSIDABCD"//WIFI账号#defineWIFI_PW"MIMA1234"//WIFI密码#defineMQTT_BROKER"192.168.123.230"//改成你的MQTTBroker地址#defineMQTT_PORT1883//改成你的MQTTBroker端口,默认18834.1.4开启PWM功能,开启方式电机驱动如下会用到PWM模块,所以需要enabledevice/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mkCONFIG_PWM_SUPPORTisnotsettoCONFIG_PWM_SUPPORT=y加上Part3中pahomqtt相关修改,以及整个Demo可以编译。4.2车控代码4.2.1查看串口日志查看WIFI连接成功,连接MQTTBroker订阅主题日志如下4.2.2电脑Windows系统下paho软件发送测试命令测试软件在附件中,或者参考连老师的说明下载和控制指令支持前进“前进”,后退“后退”,右转“右”,左转“左”,停“停”。汽车成功执行命令后,它将返回一个带有状态消息的carStatus主题。串口收到命令后,会打印如下文章。您可以点击下方链接下载原文。更多信息请访问:Harmonyos与华为技术社区共建https://harmonyos.51cto.com
