From 97d17ada7c45c6d7159ea03faedb3a673500c5de Mon Sep 17 00:00:00 2001 From: Villivateur Von Date: Mon, 20 Sep 2021 22:48:41 +0800 Subject: [PATCH] basic function OK --- doc/province_bit_map.md | 24 +++++++++++ include/client_network.h | 20 +++++++++ include/config_manager.h | 15 +++++++ include/display.h | 12 ++++++ include/func_button.h | 11 +++++ include/monitor_items.h | 10 +++++ include/status_blink.h | 21 ++++++++++ include/user_data.h | 19 +++++++++ lib/README | 46 --------------------- platformio.ini | 3 ++ src/client_network.cpp | 61 ++++++++++++++++++++++++++++ src/config_manager.cpp | 88 ++++++++++++++++++++++++++++++++++++++++ src/display.cpp | 22 ++++++++++ src/func_button.cpp | 26 ++++++++++++ src/main.cpp | 41 ++++++++++++++++--- src/status_blink.cpp | 36 ++++++++++++++++ src/user_data.cpp | 85 ++++++++++++++++++++++++++++++++++++++ test/README | 11 ----- 18 files changed, 489 insertions(+), 62 deletions(-) create mode 100644 doc/province_bit_map.md create mode 100644 include/client_network.h create mode 100644 include/config_manager.h create mode 100644 include/display.h create mode 100644 include/func_button.h create mode 100644 include/monitor_items.h create mode 100644 include/status_blink.h create mode 100644 include/user_data.h delete mode 100644 lib/README create mode 100644 src/client_network.cpp create mode 100644 src/config_manager.cpp create mode 100644 src/display.cpp create mode 100644 src/func_button.cpp create mode 100644 src/status_blink.cpp create mode 100644 src/user_data.cpp delete mode 100644 test/README diff --git a/doc/province_bit_map.md b/doc/province_bit_map.md new file mode 100644 index 0000000..33a96cc --- /dev/null +++ b/doc/province_bit_map.md @@ -0,0 +1,24 @@ +# 各省对应的 LED 位 + +此表为 Mapuino 上实际闪烁的 LED 所在省级行政区与 HTTP 报文中 `data0`、`data1` 字段的对应关系。 + +| 省 | 字段 | 位 | 省 | 字段 | 位 | +|----|-----|----|----|------|---| +| 新疆 | data0 | 0 | 内蒙古 | data0 | 1 | +| 黑龙江 | data0 | 2 | 吉林 | data0 | 3 | +| 辽宁 | data0 | 4 | 北京 | data0 | 5 | +| 天津 | data0 | 6 | 青海 | data0 | 7 | +| 甘肃 | data0 | 8 | 宁夏 | data0 | 9 | +| 陕西 | data0 | 10 | 山西 | data0 | 11 | +| 河北 | data0 | 12 | 山东 | data0 | 13 | +| 河南 | data0 | 14 | 西藏 | data0 | 15 | +| 四川 | data0 | 16 | 重庆 | data0 | 17 | +| 湖北 | data0 | 18 | 安徽 | data0 | 19 | +| 江苏 | data0 | 20 | 云南 | data0 | 21 | +| 贵州 | data0 | 22 | 湖南 | data0 | 23 | +| 江西 | data0 | 24 | 浙江 | data0 | 25 | +| 上海 | data0 | 26 | 广西 | data0 | 27 | +| 广东 | data0 | 28 | 福建 | data0 | 29 | +| 海南 | data0 | 30 | 澳门 | data0 | 31 | +| 香港 | data1 | 0 | 台湾 | data1 | 1 | +| World | data1 | 2 | \ No newline at end of file diff --git a/include/client_network.h b/include/client_network.h new file mode 100644 index 0000000..ddee7d7 --- /dev/null +++ b/include/client_network.h @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include + +class ClientNetwork +{ +private: + String url; + StaticJsonDocument<512> receivedData; + HTTPClient* http; + STATUS status; + +public: + ClientNetwork(); + STATUS FetchNewData(); + uint32_t GetData0(); + uint32_t GetData1(); +}; \ No newline at end of file diff --git a/include/config_manager.h b/include/config_manager.h new file mode 100644 index 0000000..446f3c0 --- /dev/null +++ b/include/config_manager.h @@ -0,0 +1,15 @@ +#include +#include +#include + +class ConfigManager +{ +private: + IPAddress localIp; + IPAddress gateway; + IPAddress subnet; +public: + ESP8266WebServer httpServer; + ConfigManager(); + void ProcessConfig(); +}; diff --git a/include/display.h b/include/display.h new file mode 100644 index 0000000..e75200f --- /dev/null +++ b/include/display.h @@ -0,0 +1,12 @@ +#include +#include + +class DisplayPanel +{ +private: + TM1638plus* ledMap; + +public: + DisplayPanel(); + void DisplayLedMap(uint32_t data0, uint32_t data1); +}; \ No newline at end of file diff --git a/include/func_button.h b/include/func_button.h new file mode 100644 index 0000000..e82cbc6 --- /dev/null +++ b/include/func_button.h @@ -0,0 +1,11 @@ +#include + +class FuncButton +{ +private: + uint8_t pressedTime; + +public: + FuncButton(); + void Scan(); +}; diff --git a/include/monitor_items.h b/include/monitor_items.h new file mode 100644 index 0000000..2cdfe47 --- /dev/null +++ b/include/monitor_items.h @@ -0,0 +1,10 @@ +// Topuino and Topuino_Server must share this header file + +#define CPU_PERCENT "CPU_PERCENT" +#define MEM_PERCENT "MEM_PERCENT" +#define DISK0_PERCENT "DISK_PERCENT" +#define DISK1_PERCENT "DISK1_PERCENT" +#define DISK_READ_RATE "DISK_READ_RATE" +#define DISK_WRITE_RATE "DISK_WRITE_RATE" +#define NET_SENT_RATE "NET_SENT_RATE" +#define NET_RECV_RATE "NET_RECV_RATE" \ No newline at end of file diff --git a/include/status_blink.h b/include/status_blink.h new file mode 100644 index 0000000..75b77ef --- /dev/null +++ b/include/status_blink.h @@ -0,0 +1,21 @@ +#include +#include + +#define STATUS_LED_PIN 2 + +class StatusBlink +{ +private: + Ticker flipper; + +public: + enum BlinkRate { + RateAlwaysOn, + Rate5Hz, + Rate2Hz, + Rate0_5Hz, + RateAlwaysOff, + }; + StatusBlink(); + void SetBlinkRate(BlinkRate rate); +}; \ No newline at end of file diff --git a/include/user_data.h b/include/user_data.h new file mode 100644 index 0000000..84d7456 --- /dev/null +++ b/include/user_data.h @@ -0,0 +1,19 @@ +#include + +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); +}; diff --git a/lib/README b/lib/README deleted file mode 100644 index 6debab1..0000000 --- a/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -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 a 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 -#include - -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 diff --git a/platformio.ini b/platformio.ini index 2c7f0eb..d71a46e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,3 +12,6 @@ platform = espressif8266 board = esp12e framework = arduino +lib_deps = + gavinlyonsrepo/TM1638plus@^1.7.0 + bblanchon/ArduinoJson@^6.18.3 diff --git a/src/client_network.cpp b/src/client_network.cpp new file mode 100644 index 0000000..34a4912 --- /dev/null +++ b/src/client_network.cpp @@ -0,0 +1,61 @@ +#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(userdataManager->GetWifiSsid(), userdataManager->GetWifiPasswd()); + + statusLed->SetBlinkRate(StatusBlink::BlinkRate::Rate2Hz); + while (WiFi.status() != WL_CONNECTED) + { + delay(1000); + funcButton->Scan(); + } + statusLed->SetBlinkRate(StatusBlink::BlinkRate::RateAlwaysOff); + url = "http://iot.vvzero.com/mapuino/hardwareAPI?UUID="; + url += userdataManager->GetDeviceUuid(); + status = FAIL; +} + +STATUS ClientNetwork::FetchNewData() +{ + status = FAIL; + if (WiFi.status() == WL_CONNECTED) { + WiFiClient client; + http = new HTTPClient(); + if (http->begin(client, url)) { + if (http->GET() == HTTP_CODE_OK) { + if (deserializeJson(receivedData, http->getString().c_str()) == DeserializationError::Code::Ok) { + status = OK; + } + } + http->end(); + } + delete http; + } + return status; +} + +uint32_t ClientNetwork::GetData0() +{ + if (status != OK) { + return 0; + } else { + return (uint32_t)receivedData["DATA0"]; + } +} + +uint32_t ClientNetwork::GetData1() +{ + if (status != OK) { + return 0; + } else { + return (uint32_t)receivedData["DATA1"]; + } +} diff --git a/src/config_manager.cpp b/src/config_manager.cpp new file mode 100644 index 0000000..039b486 --- /dev/null +++ b/src/config_manager.cpp @@ -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("\ +\ +\ +\ + Topuino\ + \ + \ +\ +\ +

Topuino Config Page

\ +
\ +
\ +
\ + \ + \ +
\ +
\ + \ + \ +
\ +
\ + \ + \ +
\ +
\ + \ +
\ +
\ +
\ +\ +\ +"); + + +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(); + } +} diff --git a/src/display.cpp b/src/display.cpp new file mode 100644 index 0000000..f9900d4 --- /dev/null +++ b/src/display.cpp @@ -0,0 +1,22 @@ +#include "display.h" + +#define STROBE_TM1 13 +#define CLOCK_TM 4 // clock = GPIO connected to clock line of module +#define DIO_TM 5 // data = GPIO connected to data line of module +#define HIGH_FREQ false //default false, If using a high freq CPU > ~100 MHZ set to true. + +DisplayPanel::DisplayPanel() +{ + // Constructor object (GPIO STB , GPIO CLOCK , GPIO DIO, use high freq MCU) + ledMap = new TM1638plus(STROBE_TM1, CLOCK_TM, DIO_TM, HIGH_FREQ); + ledMap->displayBegin(); +} + +void DisplayPanel::DisplayLedMap(uint32_t data0, uint32_t data1) +{ + ledMap->display7Seg(0, data0 % 0x100); + ledMap->display7Seg(1, data0 / 0x100 % 0x100); + ledMap->display7Seg(2, data0 / 0x10000 % 0x100); + ledMap->display7Seg(3, data0 / 0x1000000); + ledMap->display7Seg(4, data1 % 0x100); +} diff --git a/src/func_button.cpp b/src/func_button.cpp new file mode 100644 index 0000000..d5a0943 --- /dev/null +++ b/src/func_button.cpp @@ -0,0 +1,26 @@ +#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++; + } else { + pressedTime = 0; + } + if (pressedTime > 5) { + userdataManager->EraseData(); + ESP.restart(); + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 58b344c..820c769 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,40 @@ #include +#include "display.h" +#include "client_network.h" +#include "monitor_items.h" +#include "status_blink.h" +#include "config_manager.h" +#include "user_data.h" +#include "func_button.h" -void setup() { - // put your setup code here, to run once: +DisplayPanel* displayPanel; +ClientNetwork* netClient; +StatusBlink* statusLed; +UserData* userdataManager; +ConfigManager* configManager; +FuncButton* funcButton; + +void setup() +{ + statusLed = new StatusBlink(); + userdataManager = new UserData(); + displayPanel = new DisplayPanel(); + funcButton = new FuncButton(); + + if (!userdataManager->UserDataValid()) { + configManager = new ConfigManager(); + configManager->ProcessConfig(); + } else { + netClient = new ClientNetwork(); + } } -void loop() { - // put your main code here, to run repeatedly: -} \ No newline at end of file +void loop() +{ + delay(1000); + funcButton->Scan(); + if (netClient->FetchNewData() != OK) { + return; + } + displayPanel->DisplayLedMap(netClient->GetData0(), netClient->GetData1()); +} diff --git a/src/status_blink.cpp b/src/status_blink.cpp new file mode 100644 index 0000000..1141bf0 --- /dev/null +++ b/src/status_blink.cpp @@ -0,0 +1,36 @@ +#include "status_blink.h" + +StatusBlink::StatusBlink() +{ + pinMode(STATUS_LED_PIN, OUTPUT); + digitalWrite(STATUS_LED_PIN, HIGH); +} + +static void BlinkTask() +{ + digitalWrite(STATUS_LED_PIN, !digitalRead(STATUS_LED_PIN)); // set pin to the opposite state +} + +void StatusBlink::SetBlinkRate(BlinkRate rate) +{ + switch (rate) + { + case BlinkRate::RateAlwaysOn: + flipper.detach(); + digitalWrite(STATUS_LED_PIN, LOW); + break; + case BlinkRate::RateAlwaysOff: + flipper.detach(); + digitalWrite(STATUS_LED_PIN, HIGH); + break; + case BlinkRate::Rate5Hz: + flipper.attach(0.1, BlinkTask); + break; + case BlinkRate::Rate2Hz: + flipper.attach(0.25, BlinkTask); + break; + case BlinkRate::Rate0_5Hz: + flipper.attach(1.0, BlinkTask); + break; + } +} \ No newline at end of file diff --git a/src/user_data.cpp b/src/user_data.cpp new file mode 100644 index 0000000..b466565 --- /dev/null +++ b/src/user_data.cpp @@ -0,0 +1,85 @@ +#include "user_data.h" +#include + +#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); +} diff --git a/test/README b/test/README deleted file mode 100644 index b94d089..0000000 --- a/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PlatformIO Unit Testing 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/page/plus/unit-testing.html