279 lines
8.8 KiB
C++
279 lines
8.8 KiB
C++
#include <Adafruit_NeoPixel.h>
|
||
#include <ESP8266WiFi.h>
|
||
#include <WiFiClient.h>
|
||
#include <string.h>
|
||
#include <cstdlib>
|
||
//-------------设备配置
|
||
const char mchId[6] = "06000"; //货柜编号
|
||
bool setupFlag = false; //初始化标志
|
||
unsigned long currentTime = 0; //当前时间
|
||
//-------------LED指示灯配置
|
||
struct LEDInfo {
|
||
int ledNumber; // LED的数字编号
|
||
uint32_t color; // RGB颜色,使用NeoPixel库中的类型
|
||
int status; //状态 1=常亮 2=闪烁
|
||
int flashFlag; //闪烁状态的亮灭标识
|
||
unsigned long lastFlashTime;
|
||
};
|
||
#define NUM_LEDS 60 //LED指示灯数量
|
||
#define PIN_DIO 2 //LED控制引脚位
|
||
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN_DIO, NEO_GRB + NEO_KHZ800);
|
||
LEDInfo leds[NUM_LEDS]; // 创建一个LED信息数组
|
||
unsigned long showCheckSpace = 500; //led亮灯检测间隔,ms
|
||
unsigned long lastShowTime = 0; //上一次亮灯检测时间
|
||
//---------------wifi配置
|
||
const char* ssid = "chenyao_5G";
|
||
const char* password = "fontree008";
|
||
WiFiClient client;
|
||
//---------------服务端配置
|
||
const char* serverIP = "192.168.1.77";
|
||
const int serverPort = 8888;
|
||
const char cmd_reg[4] = "001"; //注册指令
|
||
const char cmd_ping[4] = "002"; //ping指令
|
||
char buff[512]; //tcp读取缓冲区
|
||
int rnum = 0; //tcp读取索引
|
||
bool readed = false;
|
||
void setup() {
|
||
Serial.begin(115200);
|
||
initLED();
|
||
connectWifi();
|
||
connectTcpServer();
|
||
setupFlag = true;
|
||
}
|
||
|
||
void loop() {
|
||
check();
|
||
if (setupFlag) {
|
||
bindAndHandleMessage();
|
||
ledShow();
|
||
}
|
||
// effect_colorLoop(1);
|
||
// allPixelsOn(strip.Color(255, 255, 255)); // 点亮所有LED,颜色为白色
|
||
// delay(1000);
|
||
}
|
||
//==============================================网络==========================================================
|
||
// wifi 连接
|
||
void connectWifi() {
|
||
WiFi.begin(ssid, password);
|
||
Serial.print("WIFI Connecting");
|
||
while (WiFi.status() != WL_CONNECTED) {
|
||
delay(500);
|
||
Serial.print(".");
|
||
}
|
||
Serial.println();
|
||
Serial.print("WIFI Connected, IP address: ");
|
||
Serial.println(WiFi.localIP());
|
||
}
|
||
// 连接tcp服务端
|
||
void connectTcpServer() {
|
||
Serial.print("TCP Server Connecting");
|
||
while (!client.connected()) {
|
||
if (client.connect(serverIP, serverPort)) {
|
||
delay(500);
|
||
tcpSend_register();
|
||
Serial.println();
|
||
Serial.println("TCP Server Connected");
|
||
} else {
|
||
delay(500);
|
||
Serial.print(".");
|
||
}
|
||
}
|
||
}
|
||
void check() {
|
||
if (WiFi.status() != WL_CONNECTED) {
|
||
connectWifi();
|
||
}
|
||
if (!client.connected()) {
|
||
connectTcpServer();
|
||
}
|
||
}
|
||
//==============================================LED灯效果==========================================================
|
||
// 初始化LED,使之都处于关闭状态
|
||
void initLED() {
|
||
strip.begin();
|
||
strip.show();
|
||
}
|
||
// 所有灯亮指定颜色
|
||
void allPixelsOn(uint32_t color) {
|
||
for (int i = 0; i < strip.numPixels(); i++) {
|
||
strip.setPixelColor(i, color);
|
||
}
|
||
strip.show();
|
||
}
|
||
// 红绿蓝三色循环
|
||
void effect_colorLoop(int times) {
|
||
for (int i = 0; i < times; i++) {
|
||
allPixelsOn(strip.Color(255, 0, 0));
|
||
delay(1000);
|
||
allPixelsOn(strip.Color(0, 255, 0));
|
||
delay(1000);
|
||
allPixelsOn(strip.Color(0, 0, 255));
|
||
delay(1000);
|
||
}
|
||
}
|
||
// 流水灯效果
|
||
void effect_runningWater(int times) {
|
||
for (int i = 0; i < times; i++) {
|
||
colorWipe(strip.Color(255, 0, 0), 50); // 红色流水灯
|
||
colorWipe(strip.Color(0, 255, 0), 50); // 绿色流水灯
|
||
colorWipe(strip.Color(0, 0, 255), 50); // 蓝色流水灯
|
||
}
|
||
}
|
||
// 指定一种颜色实现流水灯效果
|
||
void colorWipe(uint32_t color, int wait) {
|
||
for (int i = 0; i < strip.numPixels(); i++) {
|
||
strip.setPixelColor(i, color);
|
||
strip.show();
|
||
delay(wait);
|
||
}
|
||
}
|
||
|
||
//存储led状态
|
||
void ledSave(int ledNum, uint8_t r, uint8_t g, uint8_t b, uint8_t lig, int status) {
|
||
leds[ledNum - 1].ledNumber = ledNum;
|
||
leds[ledNum - 1].status = status;
|
||
if (lig == 0) {
|
||
leds[ledNum - 1].color = strip.Color(r, g, b);
|
||
} else {
|
||
// 使用亮度换算rgb颜色
|
||
leds[ledNum - 1].color = strip.Color((r * lig) / 255, (g * lig) / 255, (b * lig));
|
||
}
|
||
}
|
||
//轮播led灯
|
||
void ledShow() {
|
||
currentTime = millis();
|
||
if (currentTime - lastShowTime >= showCheckSpace) {
|
||
lastShowTime = currentTime;
|
||
for (int i = 0; i < NUM_LEDS; ++i) {
|
||
if (leds[i].status == 1) {
|
||
strip.setPixelColor(i, leds[i].color);
|
||
} else if (leds[i].status == 2) {
|
||
if (currentTime - leds[i].lastFlashTime >= 1000) { // 每500毫秒切换一次状态
|
||
if (leds[i].flashFlag == 0) {
|
||
strip.setPixelColor(i, leds[i].color);
|
||
} else {
|
||
strip.setPixelColor(i, strip.Color(0, 0, 0));
|
||
}
|
||
leds[i].flashFlag = !leds[i].flashFlag; // 切换flash状态
|
||
leds[i].lastFlashTime = currentTime; // 更新上次闪烁时间
|
||
}
|
||
}
|
||
}
|
||
strip.show();
|
||
}
|
||
}
|
||
//保存led状态并展示
|
||
void ledSaveAndShow(int ledNum, uint8_t r, uint8_t g, uint8_t b, uint8_t lig, int status) {
|
||
if (status == 1) {
|
||
if (lig == 0) {
|
||
leds[ledNum - 1].color = strip.Color(r, g, b);
|
||
} else {
|
||
// 计算实际的颜色值,考虑到整体亮度
|
||
leds[ledNum - 1].color = strip.Color((r * lig) / 255, (g * lig) / 255, (b * lig));
|
||
}
|
||
for (int i = 0; i < NUM_LEDS; ++i) {
|
||
strip.setPixelColor(i, leds[i].color);
|
||
}
|
||
strip.show();
|
||
}
|
||
}
|
||
//调节颜色和亮度
|
||
void setSinglePixelBrightness(int ledIndex, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) {
|
||
// 计算实际的颜色值,考虑到整体亮度
|
||
uint8_t actualRed = (r * brightness) / 255;
|
||
uint8_t actualGreen = (g * brightness) / 255;
|
||
uint8_t actualBlue = (b * brightness) / 255;
|
||
// 设置NeoPixel的颜色
|
||
strip.setPixelColor(ledIndex, strip.Color(actualRed, actualGreen, actualBlue));
|
||
}
|
||
|
||
|
||
//------------------------------------------------消息接收/发送------------------------------------------------
|
||
void bindAndHandleMessage() {
|
||
while (client.available()) {
|
||
client.readBytes(buff, sizeof(buff));
|
||
String data = String(buff);
|
||
Serial.println("acc:" + data);
|
||
readed = true;
|
||
break;
|
||
}
|
||
if (readed) {
|
||
String cmd = String(buff[0]) + String(buff[1]) + String(buff[2]);
|
||
Serial.println("Received cmd:" + cmd);
|
||
if (cmd == "002") { //ping pong
|
||
tcpSend_pong();
|
||
} else if (cmd == "003") { //led set
|
||
// int ledNum= atoi(String(buff[9]).c_str())*100+atoi(String(buff[10]).c_str())*10+atoi(String(buff[11]).c_str());
|
||
// String strLedNum=to_string(ledNum);
|
||
|
||
int ledNum = buff_int(8, 10);
|
||
int status = buff_int(11, 11);
|
||
int r = buff_int(12, 14);
|
||
int g = buff_int(15, 17);
|
||
int b = buff_int(18, 20);
|
||
int lig = buff_int(21, 23);
|
||
String strLedNum = to_string(ledNum);
|
||
String strStatus = to_string(status);
|
||
String strR = to_string(r);
|
||
String strG = to_string(g);
|
||
String strB = to_string(b);
|
||
String strLig = to_string(lig);
|
||
Serial.println("Received cmd:" + cmd + " LedNum:" + strLedNum + " status:" + strStatus + " r:" + strR + " g:" + strG + " b:" + strB + " lig:" + strLig);
|
||
ledSave(ledNum, r, g, b, lig, status);
|
||
} else {
|
||
Serial.println("Unknow cmd");
|
||
}
|
||
rnum = 0;
|
||
readed = false;
|
||
memset(buff, 0, 512);
|
||
}
|
||
}
|
||
void tcpSend_register() {
|
||
String msg = String(cmd_reg) + String(mchId);
|
||
client.println(msg);
|
||
}
|
||
void tcpSend_pong() {
|
||
String msg = String(cmd_ping) + String(mchId) + "pong";
|
||
Serial.println("send pong" + msg);
|
||
client.println(msg);
|
||
}
|
||
// void readMsg(from,to)String{
|
||
|
||
// }
|
||
//
|
||
|
||
//------------------------------------------------消息接收/发送------------------------------------------------
|
||
String to_string(int num) { // 指定返回类型为 String
|
||
String result; // 创建一个 String 对象,注意这里使用不同的变量名以避免与参数名或函数名冲突
|
||
result += num; // 将整数转换为 String 并添加到 result
|
||
return result; // 返回 String 对象
|
||
}
|
||
String buff_string(int start, int end) {
|
||
if (start < 0 || end >= sizeof(buff) || start > end) {
|
||
return ""; // 如果不在范围内,返回空字符串
|
||
}
|
||
|
||
String result;
|
||
for (int i = start; i <= end; ++i) {
|
||
result += buff[i]; // 将 buff 中的字符添加到 result 字符串中
|
||
}
|
||
return result; // 返回构建的字符串
|
||
}
|
||
int buff_int(int start, int end) {
|
||
// 检查 start 和 end 是否在 buff 的有效范围内
|
||
if (start < 0 || end >= sizeof(buff) || start > end) {
|
||
// 如果索引不合理,返回 0 或者其他错误代码
|
||
return 0;
|
||
}
|
||
|
||
// 计算子字符串的长度
|
||
int length = end - start + 1;
|
||
|
||
// 从 buff 中提取子字符串
|
||
char substr[length + 1]; // +1 为了存储字符串结束符 '\0'
|
||
strncpy(substr, &buff[start], length);
|
||
substr[length] = '\0'; // 确保字符串以 '\0' 结尾
|
||
|
||
// 将子字符串转换为整数
|
||
return atoi(substr);
|
||
} |