发 帖  

转发:【码上评选】在润和HiSpark的WiFIIoT开发板上使用 Harmony OS,实现智能花园喷灌控制系统,并连接上云

2267 HarmonyOS

在这段代码里,我们不难看出,其实最终调用的还是LiteOS的标准LOS_TaskCreate函数,并且仔细看一下函数,是可以传递参数的。我们在LiteOS官网可以找到对应线程部分的教程代码,并依葫芦画瓢,把Led模块的代码优化一下,通过传递LedSet结构体的形式,复用线程定义函数,这样我们的代码可以更简洁,更简单一些。

  1. typedef struct LedSet
    {
        /* data */
        enum LedState state;
        enum WifiIotIoName pin;
    };


  2. static void *LedTask(const struct LedSet* arg)
    {
        while (1) {
            switch (arg->state) {
                case LED_ON:
                    GpioSetOutputVal(arg->pin, 1);
                    usleep(LED_INTERVAL_TIME_US);
                    break;
                case LED_OFF:
                    GpioSetOutputVal(arg->pin, 0);
                    usleep(LED_INTERVAL_TIME_US);
                    break;
                case LED_SPARK:
                    GpioSetOutputVal(arg->pin, 1);
                    usleep(LED_INTERVAL_TIME_US);
                    GpioSetOutputVal(arg->pin, 0);
                    usleep(LED_INTERVAL_TIME_US);
                    break;
                default:
                    usleep(LED_INTERVAL_TIME_US);
                    break;
            }
        }
        return NULL;
    }

复制代码




然后在创建线程的时候,就可以通过传递不同的结构体,点亮不同的Led灯了。

  1.     green_led.state = LED_OFF;
        green_led.pin = WIFI_IOT_IO_NAME_GPIO_10;

  2.     if (osThreadNew((osThreadFunc_t)LedTask, &green_led, &attr) == NULL) {
            printf("[LedExample] Falied to create LedTask!n");
        }
复制代码


=================================================================================

虽然我们调整了结构体定义,但是这样创建3个线程,在物联网MCU的贫乏资源上浪费CPU和RAM,其实并不大好。led模块还可以通过消息队列来进行控制。我们再来学习一下消息队列的使用吧。





4、上云基础知识学习,并使用MQTT接入华为云
WiFi连接部分以及MQTT部分代码参考连老师的代码。我们现在先学习一下上云的一些理论知识。首先、设备上云并不会将完整的业务模型发布到云上,仅需要将重要的关键控制属性发布到云上。其次、可以利用物模型的服务和事件获取到更多的有用信息。



属性是通过设备影子保存在华为云上,同时应用端app(如手机端)中同步的也是设备影子上的数据。另外在设备离线时,应用端修改设备影子后,设备上线时应同步设备影子数据,与云端保持一致。





设备鉴权注意内容(以TypeScript代码为示范,代码地址https://gitee.com/walker2048/mqttclient/tree/master)



成功上报后的截图:


mqtt.h内容,将服务器信息,设备端信息等独立出来


  1. #define publish_message "{"publish":{"services":[{"service_id":"SmartPumpServer","properties":{"walterPumpSwitch":"on","pesticidePumpSwitch":"on","manurePumpSwitch":"on","manureLevels":600,"pesticideLevel":1000},"event_time":""}]}}"
    #define Hi_cloudHost "a15fbdc9af.iot-mqtts.cn-north-4.myhuaweicloud.com"
    #define Hi_deviceId "5fc9a576b4ec2202e9a32615_testDevice"                                   //设备ID
    #define Hi_deviceSecret ""                                                                  //设备secret
    #define Hi_clientId "5fc9a576b4ec2202e9a32615_testDevice_0_0_2020120512"                    //鉴权用ClientID
    #define Hi_password "1ded5f4731ab1b097edfac633a3f1cea21ab2d14ef02e1c5643fb4e08cd9415e"      //鉴权用password

  2. #define publishTopic "$oc/devices/5fc9a576b4ec2202e9a32615_testDevice/sys/messages/up"

  3. void mqtt_test(void);

  4. #endif /* __MQTT_TEST_H__ */
复制代码


mqtt.c实现内容

  1. #include

  2. #include

  3. #include "ohos_init.h"
    #include "cmsis_os2.h"

  4. #include
    #include "hi_wifi_api.h"
    //#include "wifi_sta.h"
    #include "lwip/ip_addr.h"
    #include "lwip/netifapi.h"

  5. #include "lwip/sockets.h"

  6. #include "MQTTPacket.h"
    #include "transport.h"
    #include "mqtt.h"

  7. int toStop = 0;

  8. int mqtt_connect(void)
    {

  9.     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
        int rc = 0;
        int mysock = 0;
        unsigned char buf[200];
        int buflen = sizeof(buf);
        int msgid = 1;
        MQTTString topicString = MQTTString_initializer;
        int req_qos = 0;
        char *payload = "";
        int payloadlen = strlen(payload);
        int len = 0;
        char *host = Hi_cloudHost;
        int port = 1883;

  10.     mysock = transport_open(host, port);
        if (mysock < 0)
            return mysock;

  11.     printf("Sending to hostname %s port %dn", host, port);

  12.     data.clientID.cstring = Hi_clientId;
        data.keepAliveInterval = 20;
        data.cleansession = 1;
        data.username.cstring = Hi_deviceId;
        data.password.cstring = Hi_password;

  13.     len = MQTTSerialize_connect(buf, buflen, &data);
        rc = transport_sendPacketBuffer(mysock, buf, len);

  14.     /* wait for connack */
        if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK)
        {
            unsigned char sessionPresent, connack_rc;

  15.         if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0)
            {
                printf("Unable to connect, return code %dn", connack_rc);
                goto exit;
            }
        }
        else
            goto exit;
       
        /* loop getting msgs on subscribed topic */
        topicString.cstring = "$oc/devices/5fc9a576b4ec2202e9a32615_testDevice/sys/properties/report";
        /* transport_getdata() has a built-in 1 second timeout,
            your mileage will vary */
        if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH)
        {
            unsigned char dup;
            int qos;
            unsigned char retained;
            unsigned short msgid;
            int payloadlen_in;
            unsigned char *payload_in;
            int rc;
            MQTTString receivedTopic;
            rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
                                         &payload_in, &payloadlen_in, buf, buflen);
            printf("message arrived %.*sn", payloadlen_in, payload_in);

  16.         rc = rc;
        }

  17.     printf("publishing device messagen");
        len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char *)payload, payloadlen);
        rc = transport_sendPacketBuffer(mysock, buf, len);

  18.     printf("disconnectingn");
        len = MQTTSerialize_disconnect(buf, buflen);
        rc = transport_sendPacketBuffer(mysock, buf, len);
    exit:
        transport_close(mysock);

  19.     rc = rc;

  20.     return 0;
    }

  21. void mqtt_test(void)
    {
        mqtt_connect();
    }
复制代码

5、使用 Harmony OS  的 KV 组件实现本地数据存储
6、使用 Harmony OS  的 RTC 实时时钟功能实现定时管理
使用lwip的精简校时功能third_partylwipsrcappssntpsntp.c
功能未经测试,udp_recv函数未实现

  1. #include
    #include
    #include "ohos_init.h"
    #include "cmsis_os2.h"

  2. #include "sntp.h"
    #include "sntp_opts.h"
    #include "hi_time.h"

  3. uint32_t sntp_time;

  4. void init_sntp(void)
    {
        uint32_t time = hi_get_real_time();

  5.     //加入授时中心的IP信息
        sntp_setservername(0, "ntp1.aliyun.com");
        //设置 SNTP 的获取方式 -> 使用向服务器获取方式
        sntp_setoperatingmode(SNTP_OPMODE_POLL);
        //SNTP 初始化
        sntp_init();
    }

  6. void sntp_init(void)
    {
        SNTP_RESET_RETRY_TIMEOUT();

  7.     //创建udp,用于接收udp包,时间数据
        int sntp_PCB = udp_new();
        LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
        if (sntp_pcb != NULL)
        {

  8.         //有数据,处理接收数据,同步到本地,由sntp_recv处理。
            udp_recv(sntp_pcb, sntp_set_time, NULL);
            sntp_request(NULL);
        }
    }

  9. void sntp_set_time()
    {
        if (sntp_time == 0)
        {
            print_log("sntp_set_time: wrong!@@n");
            return;
        }

  10.     print_log("sntp_set_time: c00, enter!n");
        print_log("sntp_set_time: c01, get time = %un", sntp_time);

  11.     struct tm *time;
        struct tm *sTime;

  12.     sntp_time += (8 * 60 * 60); ///北京时间是东8区需偏移8小时

  13.     time = localtime(&sntp_time);
        /*
         * 设置 RTC 的 时间
         */

  14.     hi_set_real_time(time);

  15.     print_log("sntp_set_time: c02, decode time: 20%d-%02d-%02d %d:%d:%dn",
                  time->tm_year, time->tm_mon, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec);

  16.     print_log("sntp_set_time: c03, test get = %un", get_timestamp());
        print_log("sntp_set_time: c04, set rtc time donen");
    }
复制代码

作者:忙碌的死龙







0
2020-12-25 18:35:52   评论 分享淘帖 邀请回答 举报

只有小组成员才能发言,加入小组>>

2090个成员聚集在这个小组

加入小组

创建小组步骤

快速回复 返回顶部 返回列表
关注微信公众号

电子发烧友网

电子发烧友论坛

社区合作
刘勇
联系电话:15994832713
邮箱地址:liuyong@huaqiu.com
社区管理
elecfans短短
微信:elecfans_666
邮箱:users@hauqiu.com
关闭

站长推荐 上一条 /6 下一条

快速回复 返回顶部 返回列表