ソースを参照

feature(平台): 添加openLuat平台接口

RyanCW 1 年間 前
コミット
7697d3fbe2

+ 259 - 0
platform/openLuat/platformNetwork.c

@@ -0,0 +1,259 @@
+#define rlogEnable 1             // 是否使能日志
+#define rlogColorEnable 1        // 是否使能日志颜色
+#define rlogLevel (rlogLvlError) // 日志打印等级
+#define rlogTag "RyanMqttNet"    // 日志tag
+
+#include "platformNetwork.h"
+#include "RyanMqttLog.h"
+
+/**
+ * @brief 连接mqtt服务器
+ *
+ * @param userData
+ * @param platformNetwork
+ * @param host
+ * @param port
+ * @return RyanMqttError_e
+ * 成功返回RyanMqttSuccessError, 失败返回错误信息
+ */
+RyanMqttError_e platformNetworkConnect(void *userData, platformNetwork_t *platformNetwork, const char *host, const char *port)
+{
+    RyanMqttError_e result = RyanMqttSuccessError;
+
+    // ?线程安全版本,有些设备没有实现,默认不启用。如果涉及多个客户端解析域名请使用线程安全版本
+    char buf[512];
+    int ret;
+    struct hostent hostinfo, *phost;
+
+    if (0 != gethostbyname_r(host, &hostinfo, buf, sizeof(buf), &phost, &ret))
+    {
+        result = RyanSocketFailedError;
+        goto exit;
+    }
+
+    platformNetwork->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+    if (platformNetwork->socket < 0)
+    {
+        result = RyanSocketFailedError;
+        goto exit;
+    }
+
+    struct sockaddr_in server_addr;
+    memset(&server_addr, 0, sizeof(server_addr));
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port = htons(atoi(port)); // 指定端口号,这里使用HTTP默认端口80
+    server_addr.sin_addr = *((struct in_addr *)hostinfo.h_addr_list[0]);
+
+    // 绑定套接字到主机地址和端口号
+    if (connect(platformNetwork->socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
+    {
+        platformNetworkClose(userData, platformNetwork);
+        result = RyanMqttSocketConnectFailError;
+        goto exit;
+    }
+
+    // 非线程安全版本,请根据实际情况选择使用
+    // struct hostent *hostinfo;
+    // hostinfo = gethostbyname(host);
+    // if (NULL == hostinfo)
+    // {
+    //     result = RyanSocketFailedError;
+    //     goto exit;
+    // }
+
+    // platformNetwork->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+    // if (platformNetwork->socket < 0)
+    // {
+    //     result = RyanSocketFailedError;
+    //     goto exit;
+    // }
+
+    // struct sockaddr_in server_addr;
+    // memset(&server_addr, 0, sizeof(server_addr));
+    // server_addr.sin_family = AF_INET;
+    // server_addr.sin_port = htons(atoi(port)); // 指定端口号,这里使用HTTP默认端口80
+    // server_addr.sin_addr = *((struct in_addr *)hostinfo->h_addr_list[0]);
+
+    // // 绑定套接字到主机地址和端口号
+    // if (connect(platformNetwork->socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
+    // {
+    //     platformNetworkClose(userData, platformNetwork);
+    //     result = RyanMqttSocketConnectFailError;
+    //     goto exit;
+    // }
+
+exit:
+    return result;
+}
+
+/**
+ * @brief 非阻塞接收数据
+ *
+ * @param userData
+ * @param platformNetwork
+ * @param recvBuf
+ * @param recvLen
+ * @param timeout
+ * @return RyanMqttError_e
+ * socket错误返回 RyanSocketFailedError
+ * 接收超时或者接收数据长度不等于期待数据接受长度 RyanMqttRecvPacketTimeOutError
+ * 接收成功 RyanMqttSuccessError
+ */
+RyanMqttError_e platformNetworkRecvAsync(void *userData, platformNetwork_t *platformNetwork, char *recvBuf, int recvLen, int timeout)
+{
+
+    int32_t recvResult = 0;
+    int32_t offset = 0;
+    int32_t timeOut2 = timeout;
+    struct timeval tv = {0};
+    platformTimer_t timer = {0};
+
+    if (-1 == platformNetwork->socket)
+        return RyanSocketFailedError;
+
+    platformTimerCutdown(&timer, timeout);
+
+    while ((offset < recvLen) && (0 != timeOut2))
+    {
+
+        tv.tv_sec = timeOut2 / 1000;
+        tv.tv_usec = timeOut2 % 1000 * 1000;
+
+        if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
+        {
+            tv.tv_sec = 0;
+            tv.tv_usec = 100;
+        }
+
+        fd_set readset;
+        int i, maxfdp1;
+
+        /* 清空可读事件描述符列表 */
+        FD_ZERO(&readset);
+
+        /* 将需要监听可读事件的描述符加入列表 */
+        FD_SET(platformNetwork->socket, &readset);
+
+        /* 等待设定的网络描述符有事件发生 */
+        i = select(platformNetwork->socket + 1, &readset, NULL, NULL, &tv);
+        if (i < 0)
+        {
+            // 下列3种表示没问题,但需要退出接收
+            if ((errno == EAGAIN ||      // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
+                 errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
+                 errno == EINTR))        // 操作被信号中断
+                break;
+
+            return RyanSocketFailedError;
+        }
+
+        /* 查看 sock 描述符上有没有发生可读事件 */
+        if (i > 0 && FD_ISSET(platformNetwork->socket, &readset))
+        {
+            recvResult = recv(platformNetwork->socket, recvBuf + offset, recvLen - offset, 0);
+
+            if (recvResult <= 0) // 小于零,表示错误,个别错误不代表socket错误
+            {
+                // 下列3种表示没问题,但需要退出接收
+                if ((errno == EAGAIN ||      // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
+                     errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
+                     errno == EINTR))        // 操作被信号中断
+                    break;
+
+                return RyanSocketFailedError;
+            }
+
+            offset += recvResult;
+        }
+
+        timeOut2 = platformTimerRemain(&timer);
+    }
+
+    if (offset != recvLen)
+        return RyanMqttRecvPacketTimeOutError;
+
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 非阻塞发送数据
+ *
+ * @param userData
+ * @param platformNetwork
+ * @param sendBuf
+ * @param sendLen
+ * @param timeout
+ * @return RyanMqttError_e
+ * socket错误返回 RyanSocketFailedError
+ * 接收超时或者接收数据长度不等于期待数据接受长度 RyanMqttRecvPacketTimeOutError
+ * 接收成功 RyanMqttSuccessError
+ */
+RyanMqttError_e platformNetworkSendAsync(void *userData, platformNetwork_t *platformNetwork, char *sendBuf, int sendLen, int timeout)
+{
+
+    int32_t sendResult = 0;
+    int32_t offset = 0;
+    int32_t timeOut2 = timeout;
+    struct timeval tv = {0};
+    platformTimer_t timer = {0};
+
+    if (-1 == platformNetwork->socket)
+        return RyanSocketFailedError;
+
+    platformTimerCutdown(&timer, timeout);
+
+    while ((offset < sendLen) && (0 != timeOut2))
+    {
+
+        tv.tv_sec = timeOut2 / 1000;
+        tv.tv_usec = timeOut2 % 1000 * 1000;
+
+        if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
+        {
+            tv.tv_sec = 0;
+            tv.tv_usec = 100;
+        }
+
+        setsockopt(platformNetwork->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置错做模式为非阻塞
+
+        sendResult = send(platformNetwork->socket, sendBuf + offset, sendLen - offset, 0);
+
+        if (sendResult <= 0) // 小于零,表示错误,个别错误不代表socket错误
+        {
+            // 下列3种表示没问题,但需要推出发送
+            if ((errno == EAGAIN ||      // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
+                 errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
+                 errno == EINTR))        // 操作被信号中断
+                break;
+
+            return RyanSocketFailedError;
+        }
+
+        offset += sendResult;
+        timeOut2 = platformTimerRemain(&timer);
+    }
+
+    if (offset != sendLen)
+        return RyanMqttSendPacketTimeOutError;
+
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 断开mqtt服务器连接
+ *
+ * @param userData
+ * @param platformNetwork
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformNetworkClose(void *userData, platformNetwork_t *platformNetwork)
+{
+
+    if (platformNetwork->socket >= 0)
+    {
+        closesocket(platformNetwork->socket);
+        platformNetwork->socket = -1;
+    }
+
+    return RyanMqttSuccessError;
+}

+ 38 - 0
platform/openLuat/platformNetwork.h

@@ -0,0 +1,38 @@
+#ifndef __platformNetwork__
+#define __platformNetwork__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/time.h>
+#include "RyanMqttPublic.h"
+#include "platformTimer.h"
+
+#include "common_api.h"
+#include "lwip/ip4_addr.h"
+#include "lwip/opt.h"
+#include "lwip/sys.h"
+#include "lwip/api.h"
+#include "lwip/sockets.h"
+#include "lwip/netdb.h"
+
+    typedef struct
+    {
+        int socket;
+    } platformNetwork_t;
+
+    extern RyanMqttError_e platformNetworkConnect(void *userData, platformNetwork_t *platformNetwork, const char *host, const char *port);
+    extern RyanMqttError_e platformNetworkRecvAsync(void *userData, platformNetwork_t *platformNetwork, char *recvBuf, int recvLen, int timeout);
+    extern RyanMqttError_e platformNetworkSendAsync(void *userData, platformNetwork_t *platformNetwork, char *sendBuf, int sendLen, int timeout);
+    extern RyanMqttError_e platformNetworkClose(void *userData, platformNetwork_t *platformNetwork);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 224 - 0
platform/openLuat/platformSystem.c

@@ -0,0 +1,224 @@
+
+#include "platformSystem.h"
+
+/**
+ * @brief 申请内存
+ *
+ * @param size
+ * @return void*
+ */
+inline void *platformMemoryMalloc(size_t size)
+{
+    return luat_heap_malloc(size);
+}
+
+/**
+ * @brief 释放内存
+ *
+ * @param ptr
+ */
+inline void platformMemoryFree(void *ptr)
+{
+    luat_heap_free(ptr);
+}
+
+/**
+ * @brief ms延时
+ *
+ * @param ms
+ */
+inline void platformDelay(uint32_t ms)
+{
+    osDelay(ms);
+}
+
+/**
+ * @brief 打印字符串函数,可通过串口打印出去
+ *
+ * @param str
+ * @param strLen
+ */
+inline void platformPrint(char *str, uint16_t strLen)
+{
+    luat_debug_print("%.*s", strLen, str);
+}
+
+/**
+ * @brief 初始化并运行线程
+ *
+ * @param userData
+ * @param platformThread
+ * @param name
+ * @param entry
+ * @param param
+ * @param stackSize
+ * @param priority
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformThreadInit(void *userData,
+                                   platformThread_t *platformThread,
+                                   const char *name,
+                                   void (*entry)(void *),
+                                   void *const param,
+                                   uint32_t stackSize,
+                                   uint32_t priority)
+{
+
+    const osThreadAttr_t myTask02_attributes = {
+        .name = name,
+        .stack_size = stackSize,
+        .priority = (osPriority_t)priority,
+    };
+
+    platformThread->thread = osThreadNew(entry, param, &myTask02_attributes);
+
+    if (NULL == platformThread->thread)
+        return RyanMqttNoRescourceError;
+
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 销毁自身线程
+ *
+ * @param userData
+ * @param platformThread
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformThreadDestroy(void *userData, platformThread_t *platformThread)
+{
+    osThreadExit();
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 开启线程
+ *
+ * @param userData
+ * @param platformThread
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformThreadStart(void *userData, platformThread_t *platformThread)
+{
+    osThreadResume(platformThread->thread);
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 挂起线程
+ *
+ * @param userData
+ * @param platformThread
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformThreadStop(void *userData, platformThread_t *platformThread)
+{
+    osThreadSuspend(platformThread->thread);
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 互斥锁初始化
+ *
+ * @param userData
+ * @param platformMutex
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformMutexInit(void *userData, platformMutex_t *platformMutex)
+{
+
+    const osMutexAttr_t myMutex01_attributes = {
+        .name = "mqttMutex", .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust};
+
+    platformMutex->mutex = osMutexNew(&myMutex01_attributes);
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 销毁互斥锁
+ *
+ * @param userData
+ * @param platformMutex
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformMutexDestroy(void *userData, platformMutex_t *platformMutex)
+{
+    osMutexDelete(platformMutex->mutex);
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 阻塞获取互斥锁
+ *
+ * @param userData
+ * @param platformMutex
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformMutexLock(void *userData, platformMutex_t *platformMutex)
+{
+    osMutexAcquire(platformMutex->mutex, osWaitForever);
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 释放互斥锁
+ *
+ * @param userData
+ * @param platformMutex
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformMutexUnLock(void *userData, platformMutex_t *platformMutex)
+{
+    osMutexRelease(platformMutex->mutex);
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 临界区初始化
+ *
+ * @param userData
+ * @param platformCritical
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformCriticalInit(void *userData, platformCritical_t *platformCritical)
+{
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 销毁临界区
+ *
+ * @param userData
+ * @param platformCritical
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e platformCriticalDestroy(void *userData, platformCritical_t *platformCritical)
+{
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 进入临界区
+ *
+ * @param userData
+ * @param platformCritical
+ * @return RyanMqttError_e
+ */
+inline RyanMqttError_e platformCriticalEnter(void *userData, platformCritical_t *platformCritical)
+{
+    osKernelLock();
+    return RyanMqttSuccessError;
+}
+
+/**
+ * @brief 退出临界区
+ *
+ * @param userData
+ * @param platformCritical
+ * @return RyanMqttError_e
+ */
+inline RyanMqttError_e platformCriticalExit(void *userData, platformCritical_t *platformCritical)
+{
+    osKernelUnlock();
+    return RyanMqttSuccessError;
+}

+ 65 - 0
platform/openLuat/platformSystem.h

@@ -0,0 +1,65 @@
+#ifndef __platformSystem__
+#define __platformSystem__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include "RyanMqttPublic.h"
+#include "cmsis_os2.h"
+#include "luat_debug.h"
+#include "luat_malloc.h"
+
+#define RyanMqttAssert(EX) assert(EX)
+
+    typedef struct
+    {
+        osThreadId_t thread;
+    } platformThread_t;
+
+    typedef struct
+    {
+        osMutexId_t mutex;
+    } platformMutex_t;
+
+    typedef struct
+    {
+        uint8_t invalid; // 不使用,避免报错
+    } platformCritical_t;
+
+    extern void *platformMemoryMalloc(size_t size);
+    extern void platformMemoryFree(void *ptr);
+
+    extern void platformPrint(char *str, uint16_t strLen);
+    extern void platformDelay(uint32_t ms);
+
+    extern RyanMqttError_e platformThreadInit(void *userData,
+                                              platformThread_t *platformThread,
+                                              const char *name,
+                                              void (*entry)(void *),
+                                              void *const param,
+                                              uint32_t stackSize,
+                                              uint32_t priority);
+    extern RyanMqttError_e platformThreadDestroy(void *userData, platformThread_t *platformThread);
+    extern RyanMqttError_e platformThreadStart(void *userData, platformThread_t *platformThread);
+    extern RyanMqttError_e platformThreadStop(void *userData, platformThread_t *platformThread);
+
+    extern RyanMqttError_e platformMutexInit(void *userData, platformMutex_t *platformMutex);
+    extern RyanMqttError_e platformMutexDestroy(void *userData, platformMutex_t *platformMutex);
+    extern RyanMqttError_e platformMutexLock(void *userData, platformMutex_t *platformMutex);
+    extern RyanMqttError_e platformMutexUnLock(void *userData, platformMutex_t *platformMutex);
+
+    extern RyanMqttError_e platformCriticalInit(void *userData, platformCritical_t *platformCritical);
+    extern RyanMqttError_e platformCriticalDestroy(void *userData, platformCritical_t *platformCritical);
+    extern RyanMqttError_e platformCriticalEnter(void *userData, platformCritical_t *platformCritical);
+    extern RyanMqttError_e platformCriticalExit(void *userData, platformCritical_t *platformCritical);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 68 - 0
platform/openLuat/platformTimer.c

@@ -0,0 +1,68 @@
+
+
+#include "platformTimer.h"
+
+uint32_t platformUptimeMs(void)
+{
+    if (1000 == osKernelGetTickFreq())
+        return (uint32_t)osKernelGetTickCount();
+    else
+    {
+        uint32_t tick = 0;
+        tick = osKernelGetTickCount() * 1000;
+        return (uint32_t)((tick + osKernelGetTickCount() - 1) / osKernelGetTickCount());
+    }
+}
+
+/**
+ * @brief 初始化定时器
+ *
+ * @param platformTimer
+ */
+void platformTimerInit(platformTimer_t *platformTimer)
+{
+    platformTimer->time = 0;
+    platformTimer->timeOut = 0;
+}
+
+/**
+ * @brief 添加计数时间
+ *
+ * @param platformTimer
+ * @param timeout
+ */
+void platformTimerCutdown(platformTimer_t *platformTimer, uint32_t timeout)
+{
+    platformTimer->timeOut = timeout;
+    platformTimer->time = platformUptimeMs();
+}
+
+/**
+ * @brief 计算time还有多长时间超时,考虑了32位溢出判断
+ *
+ * @param platformTimer
+ * @return uint32_t 返回剩余时间,超时返回0
+ */
+uint32_t platformTimerRemain(platformTimer_t *platformTimer)
+{
+    uint32_t tnow = platformUptimeMs();
+    uint32_t overTime = platformTimer->time + platformTimer->timeOut;
+    // uint32_t 没有溢出
+    if (overTime >= platformTimer->time)
+    {
+        // tnow溢出,不存在时间超时可能性
+        if (tnow < platformTimer->time)
+            return (UINT32_MAX - overTime + tnow + 1);
+
+        // tnow没有溢出
+        return tnow >= overTime ? 0 : (overTime - tnow);
+    }
+
+    // uint32_t 溢出了
+    // tnow 溢出了
+    if (tnow < platformTimer->time)
+        return tnow >= overTime ? 0 : (overTime - tnow + 1);
+
+    // tnow 没有溢出
+    return UINT32_MAX - tnow + overTime + 1;
+}

+ 25 - 0
platform/openLuat/platformTimer.h

@@ -0,0 +1,25 @@
+#ifndef __platformTimer__
+#define __platformTimer__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <stdint.h>
+#include "cmsis_os2.h"
+
+    typedef struct
+    {
+        uint32_t time;
+        uint32_t timeOut;
+    } platformTimer_t;
+
+    extern uint32_t platformUptimeMs(void);
+    extern void platformTimerInit(platformTimer_t *platformTimer);
+    extern void platformTimerCutdown(platformTimer_t *platformTimer, uint32_t timeout);
+    extern uint32_t platformTimerRemain(platformTimer_t *platformTimer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 21 - 0
xmake.lua

@@ -0,0 +1,21 @@
+csdk_root = "../../../" --csdk根目录,可自行修改
+includes(csdk_root.."csdk.lua")
+-- description_common()
+
+
+target("RyanMqtt",function()
+    set_kind("static")
+
+    description_csdk()
+
+    --加入代码和头文件
+    add_includedirs('./common', {public = true})
+    add_includedirs('./pahoMqtt', {public = true})
+    add_includedirs('./mqttclient', {public = true})
+    add_includedirs('./platform/openLuat', {public = true})
+
+    add_files('./common/*.c', {public = true})
+    add_files('./pahoMqtt/*.c', {public = true})
+    add_files('./mqttclient/*.c', {public = true})
+    add_files('./platform/openLuat/*.c', {public = true})
+end)