第一次同步

This commit is contained in:
2025-09-30 19:04:02 +08:00
parent 10350699d8
commit 5e938eaa70
19 changed files with 617 additions and 1 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

10
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

View File

@@ -1 +0,0 @@
# 12

39
include/README Normal file
View File

@@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
lib/README Normal file
View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

17
platformio.ini Normal file
View File

@@ -0,0 +1,17 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
upload_speed = 921600
monitor_speed = 115200
lib_deps = knolleary/PubSubClient@^2.8

67
src/Global/Macro.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef _MACRO_H__
#define _MACRO_H__
#include <Arduino.h>
/* 时间类,函数 */
#define 延时 delay
#define 延时毫秒 delay
#define 延时微秒 delayMicroseconds
#define 获取时间 millis
#define 获取微秒 micros
#define 获取毫秒 millis
#define 转字符串(expr) printf("%s\r\n", #expr)
#define 拼接字符串(A,B) A##B
/* 硬件类函数 */
#define 硬件复位 ESP.restart
#define 引脚模式 pinMode
#define 引脚写入 digitalWrite
#define 引脚读取 digitalRead
#define 模拟引脚读取 analogRead
#define 模拟引脚写入 analogWrite
#define 模拟引脚频率 analogWriteFreq
#define 模拟引脚分辨率 analogWriteResolution
/* 引脚模式 */
#define 输入模式 INPUT
#define 输出模式 OUTPUT
#define 高阻模式 INPUT_PULLUP
#define 低阻模式 INPUT_PULLDOWN_16
#define 开漏模式 INPUT_PULLUP
/* 串口类函数 */
#define 串口初始化 Serial.begin
#define 串口调试(...) Serial.printf( __VA_ARGS__)
#define 串口打印(...) Serial.print( __VA_ARGS__)
#define 串口打印换行(...) Serial.println( __VA_ARGS__)
/* 流程控制类 */
#define 循环 for
#define 如果 if
#define 否则 else
#define 否则如果 else if
#define 无限循环 while(1)
#define 判断循环 while
#define 跳出循环 break
#define 继续循环 continue
#define 返回 return
#define 空函数 void()
#define 空函数返回 void() { return; }
/* 数据类型 */
#define 字符 char
#define 字符串 String
#define 整数 int
#define 浮点数 float
#define 布尔 bool
#define 字节 byte
#define 字节指针 byte*
#define 字符指针 char*
#define 字符串指针 String*
#define 整数指针 int*
#define 浮点数指针 float*
#define 布尔指针 bool*
#endif

3
src/Global/Variable.cpp Normal file
View File

@@ -0,0 +1,3 @@
#include <Global/Variable.h>
boolean = false;
String = "";

9
src/Global/Variable.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef _VARIABLE_H__
#define _VARIABLE_H__
#include <Global/Macro.h>
#define 继电器引脚 D2
extern boolean ;
extern String ;
#endif

110
src/Mqtt/MQTT.cpp Normal file
View File

@@ -0,0 +1,110 @@
#include <Mqtt/MQTT.h>
#include <Switch/Switch.h>
Switch (D4,0,LOW);
WiFiClient WiFi客户端;
PubSubClient MQTT客户端(WiFi客户端);
//void receiveCallback(char* topic, byte* payload, unsigned int length);
// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {
String = "";
for (int i = 0; i < length; i++) {
+= static_cast<char>(payload[i]);
}
("收到主题为[%s]的消息:[%s],消息长度[%d]\n",topic,,length);
= true;
= ;
}
MQTT::MQTT()
{
}
MQTT::~MQTT()
{
}
void MQTT::(String ,int )
{
// 设置MQTT服务器和端口号
MQTT客户端.setServer(.c_str(), );
// 设置MQTT订阅回调函数
MQTT客户端.setCallback(receiveCallback);
}
void MQTT::()
{
// 设置MQTT服务器和端口号 bemfa.com 119.91.109.180
//MQTT客户端.setServer("bemfa.com",9501);
MQTT客户端.setServer("x-copper.cn",1883);
//
// 设置MQTT订阅回调函数
MQTT客户端.setCallback(receiveCallback);
}
// 连接MQTT服务器并订阅信息
bool MQTT::(){
// 根据ESP8266的MAC地址生成客户端ID避免与其它ESP8266的客户端ID重名
//String 私钥 = "de4661473e594d82ba20f50b63f0324a";
String = WiFi.macAddress();
// 连接MQTT服务器
if (MQTT客户端.connect(.c_str())) {
("MQTT服务器连接成功!\n");
(); // 订阅指定主题
} else {
("MQTT服务器连接失败!状态:[%d]\n",MQTT客户端.state());
false;
}
}
// 订阅指定主题
bool MQTT::(String ){
char subTopic[.length()];
strcpy(subTopic, .c_str());
// 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
if(MQTT客户端.subscribe(subTopic)){
("订阅成功,主题:[%s]\n",.c_str());
.();
true;
} else {
("订阅失败,主题:[%s]\n",.c_str());
.();
false;
}
}
bool MQTT::()
{
//return 订阅("SmartSwitchControl"+WiFi.macAddress()+"002");
return ("homeassistant/light/"+WiFi.macAddress()+"/command"); //homeassistant/light/807D3A177E9E/command
}
void MQTT::(String , String ){
char pubTopic[.length() + 1];
strcpy(pubTopic, .c_str());
char pubMsg[.length() + 1];
strcpy(pubMsg, .c_str());
MQTT客户端.publish(pubTopic,pubMsg);
}
void MQTT::(String ){
//String 主题 = "SmartSwitchStatus"+WiFi.macAddress()+"002";
String = "homeassistant/light/"+WiFi.macAddress()+"/state";
char pubTopic[.length() + 1];
strcpy(pubTopic, .c_str());
char pubMsg[.length() + 1];
strcpy(pubMsg, .c_str());
while (!MQTT客户端.publish(pubTopic,pubMsg))
{
(10);
}
("发布完成:主题[%s],内容:[%s]\n",pubTopic,pubMsg);
}
void MQTT::(){
MQTT客户端.loop(); // 处理信息以及心跳
}
bool MQTT::()
{
return MQTT客户端.connected();
}

24
src/Mqtt/MQTT.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef _MQTT_H__
#define _MQTT_H__
#include <Global/Variable.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
class MQTT
{
private:
public:
MQTT(); //构造函数
~MQTT(); //析构函数
void (); //MQTT初始化
void (String ,int ); //MQTT初始化
bool (); //MQTT连接
void (); //MQTT循环
bool (String ); //MQTT订阅
bool (); //MQTT订阅
void (String , String ); //MQTT发布
void (String ); //MQTT发布
bool ();
};
#endif

51
src/Switch/Switch.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include <Switch/Switch.h>
Switch::Switch(byte ,byte ,boolean ):(),(),()
{
(,);
(!=0)
(,);
digitalWrite(,);
}
Switch::~Switch()
{
}
void Switch::()//初始化引脚
{
(,);
(!=0)
(,);
digitalWrite(,);
}
byte Switch::()
{
;
}
void Switch::()
{
digitalWrite(,);
}
void Switch::()
{
digitalWrite(,!);
}
void Switch::()
{
(!=0)
digitalWrite(,!digitalRead());
digitalWrite(,!digitalRead());
}
void Switch::(boolean )
{
digitalWrite(,);
}
boolean Switch::()
{
(!=0)
digitalRead();
digitalRead();
}

24
src/Switch/Switch.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef _SWITCH_H__
#define _SWITCH_H__
#include <Global/Variable.h>
class Switch
{
private:
byte ; //控制继电器使用的引脚
byte ; //反馈继电器使用的引脚
boolean ; //继电器状态
public:
Switch(byte ,byte ,boolean = LOW); //构造函数
~Switch(); //析构函数
void (); //初始化引脚
byte (); //获取控制的引脚
void (); //打开继电器
void (); //关闭继电器
void (); //切换继电器的状态
void (boolean state); //设置继电器的状态
boolean (); //获取继电器的状态
};
#endif

19
src/Timer/Timer.cpp Normal file
View File

@@ -0,0 +1,19 @@
#include <Timer/Timer.h>
Ticker Timer1;
void TimerCD();
Timer::Timer(uint32_t t):(t)
{
//初始化定时器
Timer1.once_ms(, TimerCD); // 1000ms即1后开启timer1
}
Timer::~Timer()
{
}
void TimerCD()
{
//引脚写入(2, !引脚读取(2)); // 翻转LED引脚电平
("定时器触发\n");
}

15
src/Timer/Timer.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _TIMER_H__
#define _TIMER_H__
#include <Global/Variable.h>
#include <Ticker.h>
class Timer
{
private:
uint32_t ; //控制继电器使用的引脚
public:
Timer(uint32_t t); //构造函数
~Timer(); //析构函数
};
#endif

71
src/WiFiConfig/Config.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include <WiFiConfig/Config.h>
#include <Switch/Switch.h>
Switch _类(D4,0,LOW);
IPAddress staticIP(192, 168, 1, 22);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiConfig::WiFiConfig(int ):()
{
}
WiFiConfig::~WiFiConfig()
{
}
/**
* 一键配网关键代码
*/
void WiFiConfig::()
{
WiFi.mode(WIFI_STA);
("\n正在执行智能配网");
(500);
// 等待配网
WiFi.beginSmartConfig();
{
(".");
delay(500);
_类.();
if (WiFi.smartConfigDone())
{
("\n配网完成!WiFi名称:[%s] WiFi密码:[%s]\n",WiFi.SSID().c_str(),WiFi.psk());
WiFi.setAutoConnect(true); // 设置自动连接
break;
}
}
("\nWiFi连接成功,IP地址:[%s],Mac地址:[%s]\n",WiFi.localIP().toString().c_str(),WiFi.macAddress().c_str());
}
boolean WiFiConfig::()
{
WiFi.begin();
//如果觉得时间太长可改
for (int i = 0; i < ; i++)
{
int = WiFi.status();
_类.();
if ( == WL_CONNECTED)
{
//WiFi.config(staticIP,gateway,subnet);
("\nWiFi连接成功,WiFi名称:[%s] WiFi密码:[%s],IP地址:[%s],网关:[%s],Mac地址:[%s]\n",
WiFi.SSID().c_str(),
WiFi.psk(),
WiFi.localIP().toString().c_str(),
WiFi.gatewayIP().toString().c_str(),
WiFi.macAddress().c_str());
return true;
}
else
{
("\nWiFi自动配置,超时等待:[%d/%d]秒",i,);
delay(1000);
}
}
("WiFi自动配置失败!" );
return false;
}

20
src/WiFiConfig/Config.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef _CONFIG_H__
#define _CONFIG_H__
#include <Global/Macro.h>
#include <ESP8266WiFi.h>
class WiFiConfig
{
private:
int = 20;
public:
WiFiConfig(int = 20); //构造函数
~WiFiConfig(); //析构函数
void (); //智能配网
boolean ();
};
#endif

76
src/main.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include <Switch/Switch.h>
#include <WiFiConfig/Config.h>
#include <Mqtt/MQTT.h>
#define 配置引脚 D8 //GPIO15
MQTT MQ;
Switch (D6,0,HIGH);
Switch (D4,0,HIGH);
Switch 1(D7,0,HIGH);
Switch 2(D5,0,HIGH);
WiFiConfig 线(20);
boolean = false;
void setup() {
(115200);
(,);
// 继电器.引脚初始化();
// 指示灯.引脚初始化();
(!线.())
线.();
ESP.wdtDisable();
ESP.wdtEnable(10000);
ESP.wdtFeed();
MQ.();
//MQ.发布("on");
}
void loop() {
uint32_t = ();
(%500 == 0)
{
//指示灯.切换状态();
//判断循环(时间 == 获取时间());
ESP.wdtFeed();
}
// 如果(引脚读取(配置引脚) == LOW){
// 延时毫秒(100);
// 如果(引脚读取(配置引脚) == LOW){
// 无线网络.智能配网();
// }
// }
(MQ.()){
MQ.();
()
{
( == "on"){
.(1);
.(1);
}( == "off"){
.(0);
.(0);
}
= "";
= false;
}
( != .()){
= .();
( == 1){
MQ.("on");
("灯已打开");
}( == 0){
("灯已关闭");
MQ.("off");
}
}
}{
(%1000 == 0)
MQ.();
}
}

11
test/README Normal file
View File

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html