eefocus_3896990 发表于 2026-10-7 17:33:15

【瑞萨BLE/WIFI模块测评】+ 6、DA14531配置Wifi连接信息

本帖最后由 eefocus_3896990 于 2026-10-7 20:18 编辑

【瑞萨BLE/WIFI模块测评】+1、DA16200 模块 GUI Tool
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236549&fromuid=368655
(出处: 点点手机版网页打不开论坛)

【瑞萨BLE/WIFI模块测评】+ 2、H3003传感器数据读取
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236550&fromuid=368655
(出处: 点点手机版网页打不开论坛)

【瑞萨BLE/WIFI模块测评】+3、ISL29035光照传感器数据读取
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236551&fromuid=368655
(出处: 点点手机版网页打不开论坛)

【瑞萨BLE/WIFI模块测评】+4、DA16200 HTTP 显示传感器数据和监控按键
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236552&fromuid=368655
(出处: 点点手机版网页打不开论坛)

【瑞萨BLE/WIFI模块测评】5、DA14531蓝牙模块数据接收
//m.qjumbo.com/forum/thread-236599-1-1.html
(出处: 点点手机版网页打不开论坛)

之前的帖子实现DA14531模块的数据接收,利用DA14531模块接收包含Wifi连接信息的JSON数据,提取其中包含的Wifi连接信息,用于DA16200模块连接到Wifi网络。

# 1、添加JSON解析

定义用缓存JSON数据的缓存帧结构体和帧处理的函数声明

```c
#ifndef FRAME_RX_H
#define FRAME_RX_H

#include <stdint.h>
#include <stdbool.h>

#define FRAME_MAX_LEN 256

typedef struct {
    char buf;
    uint16_t idx;
    int depth;
    bool in_frame;
    bool in_str;
    bool escape;
    bool overflow;
} frame_rx_t;

void frame_rx_init(frame_rx_t *fr);
bool frame_rx_feed(frame_rx_t *fr, uint8_t byte);
const char *frame_rx_data(frame_rx_t *fr);

#endif
```

数据帧结构的初始化、数据输入与解析、数据帧缓存获取的函数定义如下。其中数据帧的解析用于存储获得的数据,并判断获取的数据是否满足完整的JSON数据结构。用于**的JSON数据解析。

```c
#include "frame_rx.h"
#include <string.h>

void frame_rx_init(frame_rx_t *fr) {
    fr->idx = 0;
    fr->depth = 0;
    fr->in_frame = false;
    fr->in_str = false;
    fr->escape = false;
    fr->overflow = false;
    fr->buf = '\0';
}

bool frame_rx_feed(frame_rx_t *fr, uint8_t byte) {
    /* ---------- 帧外 ---------- */
    if (!fr->in_frame) {
      if (byte == '{') {
            fr->in_frame = true;
            fr->depth = 1;
            fr->in_str = false;
            fr->escape = false;
            fr->idx = 0;
            fr->overflow = false;
            fr->buf = '{';
      }
      return false;   /* 其它字符忽略 */
    }

    /* ---------- 帧内 ---------- */
    /* 忽略 CR/LF,避免被行结束误伤 */
    if (byte == '\r' || byte == '\n') {
      return false;
    }

    /* 转义处理 */
    if (fr->escape) {
      fr->escape = false;
    } else if (byte == '\\') {
      fr->escape = true;
    } else if (byte == '"') {
      fr->in_str = !fr->in_str;
    } else if (!fr->in_str) {
      if (byte == '{') {
            fr->depth++;
      } else if (byte == '}') {
            fr->depth--;
      }
    }

    /* 存入缓冲 */
    if (fr->idx < FRAME_MAX_LEN - 1) {
      fr->buf = (char)byte;
    } else {
      fr->overflow = true;
    }

    /* 一帧结束? */
    if (fr->depth == 0) {
      fr->buf = '\0';
      fr->in_frame = false;
      fr->in_str = false;
      fr->escape = false;
      if (fr->overflow) {
            fr->overflow = false;
            return false;   /* 太长,丢弃 */
      }
      return true;
    }

    return false;
}

const char *frame_rx_data(frame_rx_t *fr) {
    return fr->buf;
}
```

JSON数据的解析和其中Wifi连接获取的数据定义如下,能够处理`{"ssid":"WiFi SSID","pass":"WIFI_PASS"}`的JSON数据。

```c
int parse_wifi_json(const char *json, char *ssid, int ssid_len,char *pass, int pass_len);

/* 从 json 中提取 key 对应的字符串值到 out */
static bool json_get_str(const char *json, const char *key, char *out, int outlen) {
    char pattern;
    snprintf(pattern, sizeof(pattern), "\"%s\"", key);
    const char *p = strstr(json, pattern);
    if (!p) return false;
    p += strlen(pattern);
    while (*p == ' ' || *p == '\t') p++;
    if (*p != ':') return false;
    p++;
    while (*p == ' ' || *p == '\t') p++;
    if (*p != '"') return false;
    p++;
    int i = 0;
    while (*p && *p != '"' && i < outlen-1) {
      if (*p == '\\' && *(p+1)) { p++; } /* 简单转义处理 */
      out = *p++;
    }
    out = '\0';
    return (*p == '"');
}

/* 返回 0 成功,-1 失败 */
int parse_wifi_json(const char *json, char *ssid, int ssid_len,
                  char *pass, int pass_len) {
    if (!json_get_str(json, "ssid", ssid, ssid_len)) return -1;
    /* 密码允许为空,但字段要存在 */
    if (!json_get_str(json, "pass", pass, pass_len)) {
      pass = '\0';
    }
    return 0;
}
```

# 2、添加BLE配置Wifi连接的代码

定义用于存储BLE数据帧的结构体变量,用于存储SSID和PASS的数组、用于判断是否接收到Wifi配置信息的变量。

```c
char ssid_buffer, pass_buffer;

static frame_rx_t s_ble_frame;
int wifi_result;
```

添加以下代码,用于获取一次通过BLE传输获得Wfii配置信息,得到的信息存储在`ssid_buffer`和`pass_buffer`数组中。

```c
frame_rx_init(&s_ble_frame);
    err = ble_transport_init();

    while (!s_wifi_busy)
    {
      ble_transport_poll();
      g_app_ble_connected = ble_transport_is_connected();

      uint8_t b;
      while (ble_get_byte(&b)) {
            if (frame_rx_feed(&s_ble_frame, b)) {
                const char *json = frame_rx_data(&s_ble_frame);

                wifi_result=parse_wifi_json(json, ssid_buffer, sizeof(ssid_buffer),
                                                      pass_buffer, sizeof(pass_buffer));

                if(wifi_result==0)
                  s_wifi_busy=true;
            }
      }

      R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
    }
```

`da16200_AT.c`中,与Wifi连接的相关代码如下,利用获取的SSID和PASS信息,构造用于Wifi连接的字符串,用于AT指令中用于连接到Wifi网络中的WFJAP指令使用。

```c
#define AP_SSID_BUF_LEN30
#define AP_PASS_BUF_LEN30

char ap_ssid;
char ap_pw;

extern char ssid_buffer, pass_buffer;

/* ---------- 构造 AT 参数字符串 ---------- */
static bool build_ap_params(const char *ssid, const char *pass)
{
    /* 安全检查:拒绝特殊字符 */
    for (const char *p = ssid; *p; p++) {
      if (*p == '\'' || *p == ',' || *p == '\\' || *p == '"') return false;
    }
    for (const char *p = pass; *p; p++) {
      if (*p == '\'' || *p == ',' || *p == '\\' || *p == '"') return false;
    }

    int n = snprintf(ap_ssid, sizeof(ap_ssid), "'%s',", ssid);
    if (n < 0 || n >= (int)sizeof(ap_ssid)) return false;

    n = snprintf(ap_pw, sizeof(ap_pw), "%s", pass);
    if (n < 0 || n >= (int)sizeof(ap_pw)) return false;

    return true;
}

    if (!build_ap_params(ssid_buffer, pass_buffer)) {

      APP_PRINT("SSID/PASS invalid or too long\r\n");

      return FSP_ERR_INVALID_ARGUMENT;

    }

    APP_PRINT("Connecting to AP: %s\r\n", ssid_buffer);

    part_array = (uint32_t)ap_ssid;
    part_array = (uint32_t)ap_pw;
    part_array = (uint32_t)at_cmd_end;
    At_cmd_combine(DA16200_AT_CMD_INDEX_AT_WFJAP, part_array, 3);
    status = AT_cmd_rcv_data(DA16200_AT_CMD_INDEX_AT_WFJAP, 4000);
    if(status != FSP_SUCCESS)
    {
      APP_PRINT("AT+WFJAPA command error!\r\n");
      return status;
    }
    else
    {
      APP_PRINT("Connect to an AP successfully!\r\n");
    }
```

# 3、总结

通过BLE模块接收串口数据,采用流控制的方式对接收到的数组进行JSON数据完整性检查和存储,接收到完整的JSON数据帧后,提取其中的Wifi连接信息用于Wifi连接。



页: [1]
查看完整版本: 【瑞萨BLE/WIFI模块测评】+ 6、DA14531配置Wifi连接信息

Baidu
map