简介
接收QQ消息,与确认收到
- 正常工作时亮蓝灯
- 当有重要的人发来消息后,亮红灯
- 点击LED按钮,则会发送确认收到,然后转亮蓝灯
- 点击按键开关,会转蓝灯,并不回复消息
效果展示
流程图
实物图
连线图
代码
/*
* 接收QQ消息,与确认收到
* 正常工作时亮蓝灯
* 当有重要的人发来消息后,亮红灯
* 此时点击按钮,则会发送确认收到,然后转亮蓝灯
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>
#include <Hash.h>
const char * ssid = "【wifi名字】";
const char * password = "【wifi密码】";
const char* HOST = "【cqhttp的IP】";
const int WsPort = 【WsPort】;
const int HttpPort = 【HttpPort】;
const String AccessToken = "【AccessToken】";
WebSocketsClient webSocket;
unsigned long messageInterval = 5000;
unsigned long lastUpdate = millis();
bool connected = false;
#define DEBUG_SERIAL Serial
int currentState = 0;
int resetState = 0;
int btnState = 0;
int brightness = 255;
String currentQQNum = "";
// 定义记录最近一次抖动的时间变量,并初始化时间为0毫秒。
long lastDebounceTime = 0;
// 定义延迟抖动的时间变量,并初始化为50毫秒。
long debounceDelay = 50;
// 是否为重要的人发来的信息
const String subQQNumArr[] = {"QQ号","QQ号"};
// 解析cqhttp发来的json数据
void parseJson(uint8_t * payload){
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload);
const char* msgTypeChar = doc["message_type"];
String msgType = msgTypeChar;
if(msgType.compareTo("private") == 0){
DEBUG_SERIAL.println("收到一条新消息");
String qqNum = doc["user_id"].as<String>();;
DEBUG_SERIAL.println(qqNum);
if(isLoverMsg(qqNum)){
currentQQNum = qqNum;
DEBUG_SERIAL.println("素素发来的");
lightBlink(true);
}
const char* rawMsg = doc["raw_message"];
DEBUG_SERIAL.printf("消息内容为:%s\n",rawMsg);
DEBUG_SERIAL.println("=========================");
}
}
void lightBlink(bool finalRed){
lightRed();
delay(100);
lightBlue();
delay(100);
lightRed();
delay(100);
lightBlue();
delay(100);
lightRed();
delay(100);
lightBlue();
delay(100);
lightRed();
delay(100);
lightBlue();
delay(100);
lightRed();
}
/*
* 是否为重要的人发来的信息
*/
bool isLoverMsg(String qqNum){
bool flag = false;
int arrLen = 0;
if(subQQNumArr[0]!=NULL){
arrLen = sizeof(subQQNumArr)/sizeof(subQQNumArr[0]);
}
for(int i = 0 ;i < arrLen;i++){
if(qqNum == subQQNumArr[i]){
return true;
}
}
return flag;
}
void sendImpMsg(String qqNum){
bool sendSuccess = esp8266Http(qqNum);
// 成功的话
if (sendSuccess) {
lightBlue();
} else {
// 闪烁一下
lightBlink(true);
}
}
// 发送HTTP请求并且将服务器响应通过串口输出
bool esp8266Http(String qqNum){
WiFiClient client; //新添加
const char* host = HOST;
const int httpPort = HttpPort;
int randomeCQCode = random(221);
// 建立字符串,用于HTTP请求
String httpRequest = String("GET /send_private_msg?user_id="+qqNum+"&access_token="+AccessToken+"&message=[CQ:face,id=109][CQ:face,id="+randomeCQCode+"]") + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n" + "\r\n";
// 通过串口输出连接服务器名称以便查阅连接服务器的网址
DEBUG_SERIAL.print("Connecting to ");
DEBUG_SERIAL.print(host);
if (client.connect(host, httpPort)){
DEBUG_SERIAL.println(" Success!");
client.print(httpRequest);
DEBUG_SERIAL.println("Sending request: ");
DEBUG_SERIAL.println(httpRequest);
DEBUG_SERIAL.println("Web Server Response:");
while (client.connected() || client.available()){
if (client.available()){
String line = client.readStringUntil('\n');
DEBUG_SERIAL.println(line);
}
}
client.stop();
DEBUG_SERIAL.print("Disconnected from "); // 并且通过串口输出断开连接信息
DEBUG_SERIAL.print(host);
return true;
} else{
DEBUG_SERIAL.println(" connection failed!");
client.stop();
return false;
}
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
DEBUG_SERIAL.printf("[WSc] Disconnected!\n");
connected = false;
break;
case WStype_CONNECTED: {
DEBUG_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
connected = true;
// send message to server when Connected
DEBUG_SERIAL.println("[WSc] SENT: Connected");
webSocket.sendTXT("Connected");
}
break;
case WStype_TEXT:
// DEBUG_SERIAL.printf("[WSc] RESPONSE: %s\n", payload);
parseJson(payload);
break;
case WStype_BIN:
DEBUG_SERIAL.printf("[WSc] get binary length: %u\n", length);
break;
case WStype_PING:
// pong will be send automatically
DEBUG_SERIAL.printf("[WSc] get ping\n");
break;
case WStype_PONG:
// answer to a ping we send
DEBUG_SERIAL.printf("[WSc] get pong\n");
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}
void setup() {
DEBUG_SERIAL.begin(115200);
DEBUG_SERIAL.println();
DEBUG_SERIAL.println();
DEBUG_SERIAL.println();
pinMode(D1,INPUT);
pinMode(D2,INPUT_PULLUP);
pinMode(D7,OUTPUT);
pinMode(D6,OUTPUT);
for(uint8_t t = 4; t > 0; t--) {
DEBUG_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
DEBUG_SERIAL.flush();
delay(1000);
}
DEBUG_SERIAL.print("Connecting to ");
DEBUG_SERIAL.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
DEBUG_SERIAL.print(".");
}
DEBUG_SERIAL.println("");
DEBUG_SERIAL.println("WiFi connected");
DEBUG_SERIAL.print("Local IP: ");
DEBUG_SERIAL.println(WiFi.localIP());
webSocket.begin(HOST, WsPort, "/?access_token="+AccessToken,"ws");
webSocket.onEvent(webSocketEvent);
lightBlue();
}
void loop() {
webSocket.loop();
if (connected && lastUpdate+messageInterval<millis()){
lastUpdate = millis();
}
btnState = digitalRead(D1);
resetState = digitalRead(D2);
// DEBUG_SERIAL.println(resetState);
if(resetState == 0){
lightBlue();
}
if(btnState != currentState){
// 1. 按钮被按下,2.并且两次按键时间间隔>抖动时间,则改变
if(btnState == 0 && (millis() - lastDebounceTime) > debounceDelay){
btnClick(currentQQNum);
// 如果按键发生了变化,则重新设置最近一次抖动的时间。
lastDebounceTime = millis();
}
currentState = btnState;
}
delay(100);
}
void btnClick(String qqNum){
sendImpMsg(qqNum);
}
void lightNone(){
analogWrite(D7,0);
analogWrite(D6,0);
}
void lightRed(){
analogWrite(D7,255);
analogWrite(D6,LOW);
}
void lightBlue(){
analogWrite(D7,LOW);
analogWrite(D6,50);
}