实现用户配置功能

This commit is contained in:
Villivateur Von 2021-08-29 22:14:08 +08:00
parent ed7d1450a6
commit 32d0f66872
12 changed files with 307 additions and 11 deletions

View File

@ -1,19 +1,25 @@
#include "client_network.h"
#include "status_blink.h"
#include "user_data.h"
#include "func_button.h"
extern StatusBlink* statusLed;
extern UserData* userdataManager;
extern FuncButton* funcButton;
ClientNetwork::ClientNetwork()
{
WiFi.begin("VVAILL", "channy161021");
{
WiFi.begin(userdataManager->GetWifiSsid(), userdataManager->GetWifiPasswd());
statusLed->SetBlinkRate(StatusBlink::BlinkRate::Rate2Hz);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
delay(1000);
funcButton->Scan();
}
statusLed->SetBlinkRate(StatusBlink::BlinkRate::RateAlwaysOff);
url = "http://iot.vvzero.com/topuino/getdata?UUID=";
url += userdataManager->GetDeviceUuid();
status = FAIL;
}
@ -23,7 +29,7 @@ STATUS ClientNetwork::FetchNewData()
if (WiFi.status() == WL_CONNECTED) {
WiFiClient client;
http = new HTTPClient();
if (http->begin(client, "http://iot.vvzero.com/topuino/getdata?UUID=1e788f28-7a5e-4888-96ff-71ab8b1876f8")) {
if (http->begin(client, url)) {
if (http->GET() == HTTP_CODE_OK) {
if (deserializeJson(receivedData, http->getString().c_str()) == DeserializationError::Code::Ok) {
status = OK;

View File

@ -7,6 +7,7 @@
class ClientNetwork
{
private:
String url;
StaticJsonDocument<512> receivedData;
HTTPClient* http;
STATUS status;

88
src/config_manager.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "config_manager.h"
#include "status_blink.h"
#include "user_data.h"
#define SSID "Topuino"
#define PASSWORD "vvzero.com"
extern StatusBlink* statusLed;
extern ConfigManager* configManager;
extern UserData* userdataManager;
static String configPage("\
<!DOCTYPE html>\
<html>\
<head>\
<title>Topuino</title>\
<meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no' />\
<link rel='shortcut icon' href='data:,'>\
</head>\
<body>\
<h1 style='text-align: center; font-size: 40px'>Topuino Config Page</h1>\
<form action='/setup' method='POST'>\
<div style='text-align: center'>\
<div style='font-size: 20px; margin-bottom: 15px'>\
<label for='ssid'><b>Wi-Fi SSID</b></label>\
<input type='text' name='ssid' required>\
</div>\
<div style='font-size: 20px; margin-bottom: 15px'>\
<label for='psw'><b>Wi-Fi Password</b></label>\
<input type='password' name='psw' required>\
</div>\
<div style='font-size: 20px; margin-bottom: 15px'>\
<label for='uuid'><b>Device ID</b></label>\
<input type='text' name='uuid' required>\
</div>\
<div style='font-size: 20px'>\
<button type='submit'>Commit</button>\
</div>\
</div>\
</form>\
</body>\
</html>\
");
static void handleOnConnect()
{
configManager->httpServer.send(200, "text/html", configPage);
}
static void handleOnCommit()
{
if (configManager->httpServer.hasArg("ssid") && configManager->httpServer.hasArg("psw") && configManager->httpServer.hasArg("uuid")) {
userdataManager->SetWifiSsid(configManager->httpServer.arg("ssid"));
userdataManager->SetWifiPasswd(configManager->httpServer.arg("psw"));
userdataManager->SetDeviceUuid(configManager->httpServer.arg("uuid"));
userdataManager->ConfirmData();
configManager->httpServer.send(200, "text/html", "OK");
delay(200);
ESP.restart();
} else {
configManager->httpServer.send(200, "text/html", "ERROR");
}
}
ConfigManager::ConfigManager() :
localIp(192,168,1,1),
gateway(192,168,1,1),
subnet(255,255,255,0),
httpServer(80)
{
statusLed->SetBlinkRate(StatusBlink::BlinkRate::Rate0_5Hz);
WiFi.softAPConfig(localIp, gateway, subnet);
WiFi.softAP(SSID, PASSWORD);
delay(100);
httpServer.on("/", handleOnConnect);
httpServer.on("/setup", handleOnCommit);
httpServer.begin();
}
void ConfigManager::ProcessConfig()
{
while (1) {
httpServer.handleClient();
}
}

15
src/config_manager.h Normal file
View File

@ -0,0 +1,15 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
class ConfigManager
{
private:
IPAddress localIp;
IPAddress gateway;
IPAddress subnet;
public:
ESP8266WebServer httpServer;
ConfigManager();
void ProcessConfig();
};

31
src/config_page.html Normal file
View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Topuino</title>
<meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no' />
<link rel='shortcut icon' href='data:,'>
</head>
<body>
<h1 style='text-align: center; font-size: 40px'>Topuino Config Page</h1>
<form action='/setup' method='POST'>
<div style='text-align: center'>
<div style='font-size: 20px; margin-bottom: 15px'>
<label for='ssid'><b>Wi-Fi SSID</b></label>
<input type='text' name='ssid' required>
</div>
<div style='font-size: 20px; margin-bottom: 15px'>
<label for='psw'><b>Wi-Fi Password</b></label>
<input type='password' name='psw' required>
</div>
<div style='font-size: 20px; margin-bottom: 15px'>
<label for='uuid'><b>Device ID</b></label>
<input type='text' name='uuid' required>
</div>
<div style='font-size: 20px'>
<button type='submit'>Commit</button>
</div>
</div>
</form>
</body>
</html>

24
src/func_button.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "func_button.h"
#include "user_data.h"
#define FUNC_BTN 0
#define PRESSED_STATUS LOW
extern UserData* userdataManager;
FuncButton::FuncButton()
{
pinMode(FUNC_BTN, INPUT);
pressedTime = 0;
}
void FuncButton::Scan()
{
if (digitalRead(FUNC_BTN) == PRESSED_STATUS) {
pressedTime++;
}
if (pressedTime > 5) {
userdataManager->EraseData();
ESP.restart();
}
}

11
src/func_button.h Normal file
View File

@ -0,0 +1,11 @@
#include <Arduino.h>
class FuncButton
{
private:
uint8_t pressedTime;
public:
FuncButton();
void Scan();
};

View File

@ -3,16 +3,30 @@
#include "client_network.h"
#include "monitor_items.h"
#include "status_blink.h"
#include "config_manager.h"
#include "user_data.h"
#include "func_button.h"
DisplayPanel* displayPanel;
ClientNetwork* netClient;
StatusBlink* statusLed;
UserData* userdataManager;
ConfigManager* configManager;
FuncButton* funcButton;
void setup()
{
statusLed = new StatusBlink();
userdataManager = new UserData();
displayPanel = new DisplayPanel();
netClient = new ClientNetwork();
funcButton = new FuncButton();
if (!userdataManager->UserDataValid()) {
configManager = new ConfigManager();
configManager->ProcessConfig();
} else {
netClient = new ClientNetwork();
}
}
void loop()
@ -27,4 +41,6 @@ void loop()
displayPanel->DisplayDisk1Percent(netClient->GetPercent(DISK1_PERCENT));
displayPanel->DisplayDiskRate(netClient->GetRate(DISK_READ_RATE), netClient->GetRate(DISK_WRITE_RATE));
displayPanel->DisplayNetRate(netClient->GetRate(NET_SENT_RATE), netClient->GetRate(NET_RECV_RATE));
funcButton->Scan();
}

View File

@ -23,14 +23,14 @@ void StatusBlink::SetBlinkRate(BlinkRate rate)
flipper.detach();
digitalWrite(STATUS_LED_PIN, HIGH);
break;
case BlinkRate::Rate8Hz:
flipper.attach(0.125, BlinkTask);
case BlinkRate::Rate5Hz:
flipper.attach(0.1, BlinkTask);
break;
case BlinkRate::Rate2Hz:
flipper.attach(0.5, BlinkTask);
flipper.attach(0.25, BlinkTask);
break;
case BlinkRate::Rate0_5Hz:
flipper.attach(2.0, BlinkTask);
flipper.attach(1.0, BlinkTask);
break;
}
}

View File

@ -11,7 +11,7 @@ private:
public:
enum BlinkRate {
RateAlwaysOn,
Rate8Hz,
Rate5Hz,
Rate2Hz,
Rate0_5Hz,
RateAlwaysOff,

85
src/user_data.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "user_data.h"
#include <EEPROM.h>
#define MAX_USER_DATA_SIZE 0x200
#define VALIDATION_MAGIC 0xaa
#define GENERAL_FEILD_SIZE 0x20
#define VALIDATION_OFFSET 0x00
#define SSID_OFFSET 0x20
#define PASSWORD_OFFSET 0x40
#define UUID_OFFSET 0x60
UserData::UserData()
{
EEPROM.begin(MAX_USER_DATA_SIZE);
}
String UserData::ReadEepromString(uint32_t offset)
{
String result;
char readByte;
for (uint32_t addr = offset; (readByte = EEPROM.read(addr)) != '\0'; addr++) {
result += readByte;
}
return result;
}
void UserData::WriteEepromString(String data, uint32_t offset)
{
for (uint32_t i = 0; i < data.length(); i++) {
EEPROM.write(i + offset, data[i]);
}
EEPROM.write(data.length() + offset, 0x00);
}
bool UserData::UserDataValid()
{
byte validation = EEPROM.read(VALIDATION_OFFSET);
return validation == VALIDATION_MAGIC;
}
void UserData::ConfirmData()
{
EEPROM.write(VALIDATION_OFFSET, VALIDATION_MAGIC);
EEPROM.commit();
}
void UserData::EraseData()
{
EEPROM.write(VALIDATION_OFFSET, 0x00);
EEPROM.commit();
}
String UserData::GetWifiSsid()
{
return ReadEepromString(SSID_OFFSET);
}
void UserData::SetWifiSsid(String ssid)
{
return WriteEepromString(ssid, SSID_OFFSET);
}
String UserData::GetWifiPasswd()
{
return ReadEepromString(PASSWORD_OFFSET);
}
void UserData::SetWifiPasswd(String password)
{
return WriteEepromString(password, PASSWORD_OFFSET);
}
String UserData::GetDeviceUuid()
{
return ReadEepromString(UUID_OFFSET);
}
void UserData::SetDeviceUuid(String uuid)
{
return WriteEepromString(uuid, UUID_OFFSET);
}

19
src/user_data.h Normal file
View File

@ -0,0 +1,19 @@
#include <Arduino.h>
class UserData
{
private:
String ReadEepromString(uint32_t offset);
void WriteEepromString(String data, uint32_t offset);
public:
UserData();
bool UserDataValid();
void ConfirmData();
void EraseData();
String GetWifiSsid();
void SetWifiSsid(String ssid);
String GetWifiPasswd();
void SetWifiPasswd(String password);
String GetDeviceUuid();
void SetDeviceUuid(String uuid);
};