#include #include #include "led.h" #include "beep.h" #include "button.h" #include "systick.h" // #include "led_digital_tube.h" #include "dht11.h" #include "adc.h" #include "usart1.h" #include "eeprom.h" #include "esp8266.h" #include "beep.h" // 配置:请替换为实际的 WiFi/服务器信息 #include "network_config.h" // 发送与重连周期配置(毫秒) #define SEND_INTERVAL_MS 200 // 设备发送间隔,减小此值可提高发送频率(注意网络与esp能力) #define RECONNECT_PERIOD_MS 5000 // 每次重连尝试的时间窗 #include "oled.h" #include "wfont.h" // 中文 char buf[512]; int main(void) { // NVIC优先级分组, 2bit 用于表示抢断优先级,2bit为子优先级 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); led_init(); // 初始化LED beep_init(); // 初始化 蜂鸣器 // button_init(); systick_init(); // 初始化计时器 usart1_init(115200); eeprom_init(); oled_init(); dht11_init(); adc1_init(); // 默认关闭蜂鸣器与 LED beep_off(); led_set_status(0, 0); led_set_status(1, 0); led_set_status(2, 0); // 初始化并尝试连接 WiFi 与服务器(如果需要可改为按键触发) esp8266_init(); int tcp_connected = 0; if (esp8266_connect_wifi(WIFI_SSID, WIFI_PASS)) { printf("Connected to WiFi\r\n"); // 建立 TCP 连接到服务器 if (esp8266_tcp_connect(SERVER_IP, SERVER_PORT)) { printf("TCP connect to %s:%d success\r\n", SERVER_IP, SERVER_PORT); tcp_connected = 1; // 发送设备注册消息 char reg_msg[128]; int reg_len = snprintf(reg_msg, sizeof(reg_msg), "{\"type\":\"register\",\"device_id\":\"%s\",\"action\":\"connect\"}\n", DEVICE_ID); if (reg_len > 0) { int sent = esp8266_write(reg_msg, (uint16_t)reg_len); if (sent > 0) { printf("Device registration sent: %s\r\n", reg_msg); } else { printf("Device registration send failed\r\n"); } } } else { printf("TCP connect failed\r\n"); tcp_connected = 0; } } else { printf("WiFi connect failed\r\n"); tcp_connected = 0; } printf("OLED Demo\r\n"); // oled_draw_picture(elephant128x64); // oled_draw_picture(gImage_1); // oled_fill_rect(10, 10, 118, 54); // oled_fill_rect(10, 10, 118, 54); // oled_fill(0x05); // oled_clear(); oled_draw_rect(0, 0, 127, 63); // oled_draw_text8(0, 0, "hello world"); // oled_draw_text16(0, 16, "\xce\xc2\xb6\xc8: 36.5 \xa1\xe6"); // 将缓冲区内容刷新到屏幕 // oled_refresh_framebuffer(); while (1) { char buf[30]; u8 value[5]; dht11_get_values(value); sprintf(buf, "\xce\xc2\xb6\xc8: %5.1f \xa1\xe6", (float)value[2]); // 显示温度 oled_draw_text16(8, 8, buf); sprintf(buf, "\xca\xaa\xb6\xc8: %5.1f%", (float)value[0]); // 显示湿度 oled_draw_text16(8, 24, buf); // 显示 ADC 的值(通道 10) sprintf(buf, "ADC Value: %04d", adc1_get_value(10)); oled_draw_text8(8, 40, buf); // 显示 LED 0 灯的状态(状态由服务器控制,固件不应自动切换) sprintf(buf, "LED(0): %3s", led_get_status(0) ? "ON" : "OFF"); oled_draw_text8(8, 48, buf); oled_refresh_framebuffer(); // 构造并发送 JSON 状态消息到后台服务器(TCP 行协议,每条消息以换行结束) // 仅在 TCP 已连接时发送,避免在未连接时调用 CIPSEND 导致错误 static int reconnect_counter = 0; // 每次循环增长,达到阈值时尝试重连 reconnect_counter++; int reconnect_threshold = RECONNECT_PERIOD_MS / SEND_INTERVAL_MS; if (reconnect_threshold < 1) reconnect_threshold = 1; if (!tcp_connected) { if (reconnect_counter >= reconnect_threshold) { reconnect_counter = 0; printf("Attempting TCP reconnect...\r\n"); if (esp8266_tcp_connect(SERVER_IP, SERVER_PORT)) { tcp_connected = 1; printf("TCP reconnect success\r\n"); // 重新连接后发送设备注册消息 char reg_msg[128]; int reg_len = snprintf(reg_msg, sizeof(reg_msg), "{\"type\":\"register\",\"device_id\":\"%s\",\"action\":\"reconnect\"}\n", DEVICE_ID); if (reg_len > 0) { int sent = esp8266_write(reg_msg, (uint16_t)reg_len); if (sent > 0) { printf("Device re-registration sent: %s\r\n", reg_msg); } else { printf("Device re-registration send failed\r\n"); } } } else { printf("TCP reconnect failed\r\n"); } } else { // not connected, skip sending this round printf("Not connected to TCP server, skipping send\r\n"); delay_ms(SEND_INTERVAL_MS); continue; } } char json[256]; int msg_len = snprintf(json, sizeof(json), "{\"device_id\":\"%s\",\"temp\":%.1f,\"humidity\":%.1f,\"buzzer\":%d,\"led0\":%d,\"led1\":%d,\"led2\":%d}\n", DEVICE_ID, (float)value[2], (float)value[0], beep_get_status(), led_get_status(0), led_get_status(1), led_get_status(2)); if (msg_len > 0) { esp8266_clear_read_buf(); int sent = esp8266_write(json, (uint16_t)msg_len); if (sent > 0) { printf("Sent: %s\r\n", json); } else { printf("Send failed\r\n"); } } // 主动从服务器读取控制文件(轮询模式),避免依赖广播时序 if (tcp_connected) { char getcmd[64]; snprintf(getcmd, sizeof(getcmd), "GET control %s\n", DEVICE_ID); int gsent = esp8266_write(getcmd, (uint16_t)strlen(getcmd)); if (gsent > 0) { printf("Sent GET control request\r\n"); } else { printf("Send GET control failed\r\n"); } } // 发送后尝试读取来自服务器的控制命令(如果有) char inbuf[256]; int rlen = esp8266_read(inbuf, sizeof(inbuf)); if (rlen > 0) { // 简单解析 JSON 中的 buzzer 与 led0/led1/led2 字段 // 允许格式例如: {"buzzer":1,"led0":1,"led1":0,"led2":0} inbuf[rlen] = '\0'; printf("Control recv: %s\r\n", inbuf); // 查找 buzzer char *p = NULL; int val = 0; p = strstr(inbuf, "\"buzzer\""); if (p) { p = strchr(p, ':'); if (p) { if (sscanf(p+1, "%d", &val) == 1) { if (val) { beep_on(); printf("Applied buzzer=1\r\n"); } else { beep_off(); printf("Applied buzzer=0\r\n"); } } } } // led0..led2 for (int i = 0; i < 3; i++) { char key[16]; sprintf(key, "\"led%d\"", i); p = strstr(inbuf, key); if (p) { p = strchr(p, ':'); if (p) { if (sscanf(p+1, "%d", &val) == 1) { led_set_status(i, val ? 1 : 0); printf("Applied led%d=%d\r\n", i, val ? 1 : 0); } } } } } delay_ms(SEND_INTERVAL_MS); } }