220 lines
6.6 KiB
C
220 lines
6.6 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#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);
|
|
}
|
|
}
|
|
|