esp32 s3 修改本地ip和服务器IP

复制代码
#include "driver/i2s_pdm.h"
#include "Arduino.h"
#include <WiFi.h>
#include <EEPROM.h>

/* ========== 默认参数 ========== */
const char *ssid_dft     = "123";
const char *pass_dft     = "12345678";
const int   port_dft     = 8888;
const char *eeprom_ip_dft= "192.168.107.97";
const char *local_ip_dft = "192.168.107.88";
const char *gateway_dft  = "192.168.107.1";
const char *netmask_dft  = "255.255.255.0";

/* ========== 运行期变量 ========== */
char        ssid[32]     = {0};
char        password[64] = {0};
int         server_port  = port_dft;
char        eeprom_ip[16]= {0};
char        eeprom_local_ip[16] = {0};
char        eeprom_gw[16]       = {0};
char        eeprom_mask[16]     = {0};
bool        use_static_flag     = false;
WiFiClient  client;

#define PDM_CLK_GPIO 4
#define PDM_DIN_GPIO 5
i2s_chan_handle_t rx_chan = nullptr;

/* -------- 函数声明 -------- */
void configure_i2s();
bool parse_ip_cmd(const char *line);
void load_cfg_from_eeprom();
void save_cfg_to_eeprom();
/* -------------------------- */

void setup() {
  Serial.begin(115200);
  EEPROM.begin(256);                // 128 也够用,留余量
  load_cfg_from_eeprom();           // 一次性读出全部配置

  configure_i2s();

  WiFi.begin(ssid, password);
  /* ---- 关键:静态 IP ---- */
  if (use_static_flag) {
    IPAddress lip, gw, sn;
    lip.fromString(eeprom_local_ip);
    gw .fromString(eeprom_gw);
    sn .fromString(eeprom_mask);
    WiFi.config(lip, gw, sn);
  }
  /* ----------------------- */
  while (WiFi.status() != WL_CONNECTED) delay(500);

  Serial.println("WiFi已连接");
  Serial.print("ESP32本地IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("目标服务器: ");
  Serial.print(eeprom_ip);
  Serial.print(':');
  Serial.println(server_port);

  WiFi.setTxPower(WIFI_POWER_8_5dBm);
  gpio_set_drive_capability((gpio_num_t)PDM_CLK_GPIO, GPIO_DRIVE_CAP_1);
  gpio_set_drive_capability((gpio_num_t)PDM_DIN_GPIO, GPIO_DRIVE_CAP_1);
  gpio_set_pull_mode((gpio_num_t)PDM_DIN_GPIO, GPIO_PULLUP_ONLY);
}

void loop() {
  /* 1. 串口命令接收(非阻塞) */
  static uint8_t cmd_buf[128], cmdIdx = 0;
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '\n' || c == '\r') {
      if (cmdIdx) {
        cmd_buf[cmdIdx] = 0;
        if (parse_ip_cmd((char *)cmd_buf)) {
          save_cfg_to_eeprom();
          Serial.println("Save & Restart...");
          delay(100);
          ESP.restart();
        }
        cmdIdx = 0;
      }
    } else if (cmdIdx < sizeof(cmd_buf) - 1) {
      cmd_buf[cmdIdx++] = c;
    }
  }

  /* 2. TCP 重连 */
  if (!client.connected()) {
    if (client.connect(eeprom_ip, server_port)) {
      Serial.println("TCP流已建立");
    } else {
      delay(1000);
    }
    return;
  }

  /* 3. 非阻塞读 I2S 并实时转发 */
  static int16_t buf[512];
  size_t bytes_read = 0;
  if (i2s_channel_read(rx_chan, buf, sizeof(buf), &bytes_read, portMAX_DELAY) == ESP_OK) {
    client.write((uint8_t*)buf, bytes_read);
  }
}

/* ==================== I2S 驱动 ==================== */
void configure_i2s() {
  i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
  chan_cfg.dma_desc_num = 16;
  chan_cfg.dma_frame_num = 1024;
  ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, nullptr, &rx_chan));

  i2s_pdm_rx_config_t pdm_cfg = {
      .clk_cfg  = I2S_PDM_RX_CLK_DEFAULT_CONFIG(16000),
      .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
      .gpio_cfg = { .clk = (gpio_num_t)PDM_CLK_GPIO, .din = (gpio_num_t)PDM_DIN_GPIO,
                    .invert_flags = { .clk_inv = false } },
  };
  ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_cfg));
  ESP_ERROR_CHECK(i2s_channel_enable(rx_chan));
}

/* ==================== 串口命令 & EEPROM ==================== */
//ssid=Test pass=12345678 ip=192.168.107.97 port=8888 lip=192.168.1.99 gw=192.168.1.1 mask=255.255.255.0 dhcp=0
bool parse_ip_cmd(const char *line) {
  bool changed = false;
  char tmp[128];
  strcpy(tmp, line);
  char *tok = strtok(tmp, " ");
  while (tok) {
    if (strncmp(tok, "ip=", 3) == 0) {
      unsigned int seg[4];
      if (sscanf(tok + 3, "%3u.%3u.%3u.%3u", &seg[0], &seg[1], &seg[2], &seg[3]) == 4) {
        bool ok = true;
        for (int i = 0; i < 4; ++i) if (seg[i] > 255) ok = false;
        if (ok && strlen(tok + 3) < 16) {
          strcpy(eeprom_ip, tok + 3);
          changed = true;
        }
      }
    } else if (strncmp(tok, "ssid=", 5) == 0 && strlen(tok + 5) < 32) {
      strcpy(ssid, tok + 5); changed = true;
    } else if (strncmp(tok, "pass=", 5) == 0 && strlen(tok + 5) < 64) {
      strcpy(password, tok + 5); changed = true;
    } else if (strncmp(tok, "port=", 5) == 0) {
      int p = atoi(tok + 5);
      if (p > 0 && p <= 65535) { server_port = p; changed = true; }
    }
    /* ---- 新增本地 IP 相关命令 ---- */
    else if (strncmp(tok, "lip=", 4) == 0) {
      if (strlen(tok + 4) < 16) { strcpy(eeprom_local_ip, tok + 4); changed = true; }
    } else if (strncmp(tok, "gw=", 3) == 0) {
      if (strlen(tok + 3) < 16) { strcpy(eeprom_gw, tok + 3); changed = true; }
    } else if (strncmp(tok, "mask=", 5) == 0) {
      if (strlen(tok + 5) < 16) { strcpy(eeprom_mask, tok + 5); changed = true; }
    } else if (strncmp(tok, "dhcp=", 5) == 0) {
      int d = atoi(tok + 5);
      use_static_flag = (d == 0);
      changed = true;
    }
    /* ------------------------------ */
    tok = strtok(nullptr, " ");
  }
  return changed;
}

/* ---------- EEPROM 读写 ---------- */
void load_cfg_from_eeprom() {
  struct __attribute__((packed)) cfg {
    char  ip[16];
    char  ssid[32];
    char  pass[64];
    int   port;
    bool  use_static;
    char  local_ip[16];
    char  gateway[16];
    char  netmask[16];
    uint8_t crc;
  } c;

  EEPROM.get(0, c);
  uint8_t *p = (uint8_t*)&c;
  uint8_t sum = 0;
  for (int i = 0; i < sizeof(c) - 1; ++i) sum += p[i];

  if (sum == c.crc && c.port > 0 && c.port <= 65535) {
    strcpy(eeprom_ip,        c.ip);
    strcpy(ssid,             c.ssid);
    strcpy(password,         c.pass);
    server_port             = c.port;
    use_static_flag         = c.use_static;
    strcpy(eeprom_local_ip,  c.local_ip);
    strcpy(eeprom_gw,        c.gateway);
    strcpy(eeprom_mask,      c.netmask);
    Serial.println("从EEPROM载入配置成功");
  } else {
    /* 使用默认值并立即保存一份 */
    strcpy(eeprom_ip,        eeprom_ip_dft);
    strcpy(ssid,             ssid_dft);
    strcpy(password,         pass_dft);
    server_port             = port_dft;
    use_static_flag         = false;
    strcpy(eeprom_local_ip,  local_ip_dft);
    strcpy(eeprom_gw,        gateway_dft);
    strcpy(eeprom_mask,      netmask_dft);
    save_cfg_to_eeprom();
  }
}

void save_cfg_to_eeprom() {
  struct __attribute__((packed)) cfg {
    char  ip[16];
    char  ssid[32];
    char  pass[64];
    int   port;
    bool  use_static;
    char  local_ip[16];
    char  gateway[16];
    char  netmask[16];
    uint8_t crc;
  } c;

  strcpy(c.ip,        eeprom_ip);
  strcpy(c.ssid,      ssid);
  strcpy(c.pass,      password);
  c.port              = server_port;
  c.use_static        = use_static_flag;
  strcpy(c.local_ip,  eeprom_local_ip);
  strcpy(c.gateway,   eeprom_gw);
  strcpy(c.netmask,   eeprom_mask);

  uint8_t *p = (uint8_t*)&c;
  uint8_t sum = 0;
  for (int i = 0; i < sizeof(c) - 1; ++i) sum += p[i];
  c.crc = sum;

  EEPROM.put(0, c);
  EEPROM.commit();
  Serial.println("配置已写入EEPROM");
}

ssid=Test pass=12345678 ip=192.168.107.97 port=8888 lip=192.168.1.99 gw=192.168.1.1 mask=255.255.255.0 dhcp=0,使用的是串口0,电脑直接输入即可

相关推荐
Ares-Wang15 小时前
网络》》防火墙
运维·服务器·网络
qq_4112624216 小时前
优化wifi的性能,LWIP_TCP_WND是不是指的是DYNAMIC_RX_BUFFER动态接受缓冲区的缓冲区大小
网络·网络协议·tcp/ip
默|笙16 小时前
【Linux】基础IO(1)文件、fd
linux·运维·服务器
凌波粒16 小时前
Linux高级篇-日志管理/Linux裁剪/内核源码/备份与恢复/可视化管理
linux·运维·服务器
阿杰 AJie16 小时前
如何将公司公网ip绑定到服务器和域名
服务器·网络·tcp/ip
米优16 小时前
srs媒体流服务器二次开发-实现读取配置文件功能
服务器·后端·媒体
m0_7269659816 小时前
【服务器二】下载拓展成功
运维·服务器
漉水浮沙16 小时前
cat /proc/interrupts 验证nvme 中断聚合
服务器
就叫飞六吧16 小时前
Java “跨平台”指的是(.class 字节码)跨平台,而不是指 JVM 这个软件本身跨平台
服务器·笔记