Compare commits
No commits in common. "6709f7ce2299608adb084998c086c1c1e1be3583" and "8df391e66f870f8e6c6fc8d1e96104536617a786" have entirely different histories.
6709f7ce22
...
8df391e66f
Binary file not shown.
|
Before Width: | Height: | Size: 401 KiB |
|
|
@ -1,5 +0,0 @@
|
||||||
.pio
|
|
||||||
.vscode/.browse.c_cpp.db*
|
|
||||||
.vscode/c_cpp_properties.json
|
|
||||||
.vscode/launch.json
|
|
||||||
.vscode/ipch
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
// 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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"mqtt":
|
|
||||||
{
|
|
||||||
"server": "192.168.1.80",
|
|
||||||
"port": 1883,
|
|
||||||
"username": "simon",
|
|
||||||
"password": "bajsa123",
|
|
||||||
"id": ""
|
|
||||||
},
|
|
||||||
"lora":
|
|
||||||
{
|
|
||||||
"frequency": 433775000,
|
|
||||||
"spreadingFactor": 12,
|
|
||||||
"signalBandwidth": 125000,
|
|
||||||
"codingRate4": 5,
|
|
||||||
"power": 20
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 717 B |
|
|
@ -1,27 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>ESP WEB SERVER</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png">
|
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="topnav">
|
|
||||||
<h1>ESP WEB SERVER</h1>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="card-grid">
|
|
||||||
<div class="card">
|
|
||||||
<p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 2</p>
|
|
||||||
<p>
|
|
||||||
<a href="on"><button class="button-on">ON</button></a>
|
|
||||||
<a href="off"><button class="button-off">OFF</button></a>
|
|
||||||
</p>
|
|
||||||
<p class="state">State: %STATE%</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
html {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 1.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topnav {
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: #0A1128;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 5%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-grid {
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 2rem;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-title {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #034078
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=submit] {
|
|
||||||
border: none;
|
|
||||||
color: #FEFCFB;
|
|
||||||
background-color: #034078;
|
|
||||||
padding: 15px 15px;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 16px;
|
|
||||||
width: 100px;
|
|
||||||
margin-right: 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition-duration: 0.4s;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=submit]:hover {
|
|
||||||
background-color: #1282A2;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=text], input[type=number], select {
|
|
||||||
width: 50%;
|
|
||||||
padding: 12px 20px;
|
|
||||||
margin: 18px;
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
.value{
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #1282A2;
|
|
||||||
}
|
|
||||||
.state {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #1282A2;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
border: none;
|
|
||||||
color: #FEFCFB;
|
|
||||||
padding: 15px 32px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 16px;
|
|
||||||
width: 100px;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition-duration: 0.4s;
|
|
||||||
}
|
|
||||||
.button-on {
|
|
||||||
background-color: #034078;
|
|
||||||
}
|
|
||||||
.button-on:hover {
|
|
||||||
background-color: #1282A2;
|
|
||||||
}
|
|
||||||
.button-off {
|
|
||||||
background-color: #858585;
|
|
||||||
}
|
|
||||||
.button-off:hover {
|
|
||||||
background-color: #252524;
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>ESP Wi-Fi Manager</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" href="data:,">
|
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="topnav">
|
|
||||||
<h1>ESP Wi-Fi Manager</h1>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<div class="card-grid">
|
|
||||||
<div class="card">
|
|
||||||
<form action="/" method="POST">
|
|
||||||
<p>
|
|
||||||
<label for="ssid">SSID</label>
|
|
||||||
<input type="text" id ="ssid" name="ssid"><br>
|
|
||||||
<label for="pass">Password</label>
|
|
||||||
<input type="text" id ="pass" name="pass"><br>
|
|
||||||
<label for="ip">IP Address</label>
|
|
||||||
<input type="text" id ="ip" name="ip" value="192.168.1.200"><br>
|
|
||||||
<label for="gateway">Gateway Address</label>
|
|
||||||
<input type="text" id ="gateway" name="gateway" value="192.168.1.1"><br>
|
|
||||||
<input type ="submit" value ="Submit">
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -13,12 +13,7 @@ platform = espressif32
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
build_flags =
|
|
||||||
-D DEBUG
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/tzapu/WiFiManager.git
|
|
||||||
bblanchon/ArduinoJson@^7.0.4
|
|
||||||
peterus/esp-logger@^1.0.0
|
|
||||||
knolleary/PubSubClient@^2.8
|
|
||||||
sandeepmistry/LoRa@^0.8.0
|
|
||||||
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.5.0
|
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.5.0
|
||||||
|
sandeepmistry/LoRa@^0.8.0
|
||||||
|
knolleary/PubSubClient@^2.8
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
// OLED
|
||||||
|
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||||
|
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||||
|
|
||||||
|
// LORA
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <LoRa.h>
|
||||||
|
|
||||||
|
// MQTT
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
|
|
||||||
|
SSD1306 display(0x3c, 4, 15);
|
||||||
|
|
||||||
|
//OLED pins to ESP32 GPIOs via this connection:
|
||||||
|
//OLED_SDA GPIO4
|
||||||
|
//OLED_SCL GPIO15
|
||||||
|
//OLED_RST GPIO16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// WIFI_LoRa_32 ports
|
||||||
|
|
||||||
|
// GPIO5 SX1278 SCK
|
||||||
|
// GPIO19 SX1278 MISO
|
||||||
|
// GPIO27 SX1278 MOSI
|
||||||
|
// GPIO18 SX1278 CS
|
||||||
|
// GPIO14 SX1278 RESET
|
||||||
|
// GPIO26 SX1278 IRQ(Interrupt Request)
|
||||||
|
|
||||||
|
#define SS 18
|
||||||
|
#define RST 14
|
||||||
|
#define DI0 26
|
||||||
|
// #define BAND 429E6
|
||||||
|
|
||||||
|
// LoRa Settings
|
||||||
|
#define BAND 434500000.00
|
||||||
|
#define spreadingFactor 9
|
||||||
|
// #define SignalBandwidth 62.5E3
|
||||||
|
#define SignalBandwidth 31.25E3
|
||||||
|
|
||||||
|
#define codingRateDenominator 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// WiFi Network Credentials
|
||||||
|
const char *ssid = "SoS IOT";
|
||||||
|
const char *password = "godisr8n";
|
||||||
|
|
||||||
|
// MQTTCredentials
|
||||||
|
const char *MQTT_USER = "simon";
|
||||||
|
const char *MQTT_PASS = "bajsa123";
|
||||||
|
|
||||||
|
IPAddress broker(10,0,0,3); // IP address of your MQTT broker eg. 192.168.1.50
|
||||||
|
const char *ID = "esp_1"; // Name of our device, must be unique
|
||||||
|
const char *TOPIC = "test/sensor"; // Topic to subcribe to
|
||||||
|
WiFiClient wclient;
|
||||||
|
|
||||||
|
PubSubClient client(wclient); // Setup MQTT client
|
||||||
|
|
||||||
|
String data = "";
|
||||||
|
|
||||||
|
// Connect to WiFi network
|
||||||
|
void setup_wifi() {
|
||||||
|
Serial.print("\nConnecting to ");
|
||||||
|
Serial.println(ssid);
|
||||||
|
|
||||||
|
WiFi.begin(ssid, password); // Connect to network
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) { // Wait for connection
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("WiFi connected");
|
||||||
|
Serial.print("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconnect to client
|
||||||
|
void reconnect() {
|
||||||
|
// Loop until we're reconnected
|
||||||
|
while (!client.connected()) {
|
||||||
|
Serial.print("Attempting MQTT connection...");
|
||||||
|
// Attempt to connect
|
||||||
|
if (client.connect(ID,MQTT_USER,MQTT_PASS)) {
|
||||||
|
Serial.println("connected");
|
||||||
|
Serial.print("Publishing to: ");
|
||||||
|
Serial.println(TOPIC);
|
||||||
|
Serial.println('\n');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Serial.println(" try again in 5 seconds");
|
||||||
|
// Wait 5 seconds before retrying
|
||||||
|
delay(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ADC? Battery voltage
|
||||||
|
// const uint8_t vbatPin = 34;
|
||||||
|
// float VBAT; // battery voltage from ESP32 ADC read
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(16,OUTPUT);
|
||||||
|
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
|
||||||
|
delay(50);
|
||||||
|
digitalWrite(16, HIGH);
|
||||||
|
|
||||||
|
display.init();
|
||||||
|
display.flipScreenVertically();
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
while (!Serial); //if just the the basic function, must connect to a computer
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
Serial.println("LoRa Receiver");
|
||||||
|
display.drawString(5,5,"LoRa Receiver");
|
||||||
|
display.display();
|
||||||
|
SPI.begin(5,19,27,18);
|
||||||
|
LoRa.setPins(SS,RST,DI0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
pinMode(vbatPin, INPUT);
|
||||||
|
VBAT = (120.0/20.0) * (float)(analogRead(vbatPin)) / 1024.0; // LiPo battery voltage in volts
|
||||||
|
Serial.println("Vbat = "); Serial.print(VBAT); Serial.println(" Volts");
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!LoRa.begin(BAND)) {
|
||||||
|
display.drawString(5,25,"Starting LoRa failed!");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
Serial.println("LoRa Initial OK!");
|
||||||
|
|
||||||
|
Serial.print("LoRa Frequency: ");
|
||||||
|
Serial.println(BAND);
|
||||||
|
|
||||||
|
Serial.print("LoRa Spreading Factor: ");
|
||||||
|
Serial.println(spreadingFactor);
|
||||||
|
LoRa.setSpreadingFactor(spreadingFactor);
|
||||||
|
|
||||||
|
Serial.print("LoRa Signal Bandwidth: ");
|
||||||
|
Serial.println(SignalBandwidth);
|
||||||
|
LoRa.setSignalBandwidth(SignalBandwidth);
|
||||||
|
|
||||||
|
LoRa.setCodingRate4(codingRateDenominator);
|
||||||
|
|
||||||
|
display.drawString(5,25,"LoRa Initializing OK!");
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
setup_wifi(); // Connect to network
|
||||||
|
client.setServer(broker, 1883);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (!client.connected()) // Reconnect if connection is lost
|
||||||
|
{
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
client.loop();
|
||||||
|
// try to parse packet
|
||||||
|
int packetSize = LoRa.parsePacket();
|
||||||
|
if (packetSize) {
|
||||||
|
// received a packets
|
||||||
|
Serial.print("Received packet. ");
|
||||||
|
|
||||||
|
display.clear();
|
||||||
|
display.setFont(ArialMT_Plain_16);
|
||||||
|
display.drawString(3, 0, "Received packet ");
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
// read packet
|
||||||
|
while (LoRa.available()) {
|
||||||
|
data = LoRa.readString();
|
||||||
|
Serial.print(data);
|
||||||
|
display.drawString(20,22, data);
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
// print RSSI of packet
|
||||||
|
Serial.print(" with RSSI ");
|
||||||
|
Serial.println(LoRa.packetRssi());
|
||||||
|
Serial.print(" with SNR ");
|
||||||
|
Serial.println(LoRa.packetSnr());
|
||||||
|
// display.drawString(0, 45, "RSSI: ");
|
||||||
|
// display.drawString(50, 45, (String)LoRa.packetRssi());
|
||||||
|
|
||||||
|
display.drawString(0, 45, (String)LoRa.packetRssi() + "dB (" + (String)LoRa.packetSnr() +"dB)");
|
||||||
|
|
||||||
|
display.display();
|
||||||
|
client.publish(TOPIC, data.c_str() );
|
||||||
|
Serial.println((String)TOPIC + " => " + data + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <SPIFFS.h>
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
|
|
||||||
Config::Config()
|
|
||||||
{
|
|
||||||
_filePath = "/config.json";
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Init config");
|
|
||||||
if (!SPIFFS.begin(false))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "SPIFFS Mount Failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
readFile(SPIFFS, _filePath.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::readFile(fs::FS &fs, const char *fileName)
|
|
||||||
{
|
|
||||||
JsonDocument data;
|
|
||||||
File configFile = fs.open(fileName, "r");
|
|
||||||
DeserializationError error = deserializeJson(data, configFile);
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to read file, using default configuration");
|
|
||||||
}
|
|
||||||
|
|
||||||
MqttConfig mqtt;
|
|
||||||
mqtt.server = data["mqtt"]["server"].as<String>();
|
|
||||||
mqtt.port = data["mqtt"]["port"].as<int>();
|
|
||||||
mqtt.username = data["mqtt"]["username"].as<String>();
|
|
||||||
mqtt.password = data["mqtt"]["password"].as<String>();
|
|
||||||
mqtt.id = data["mqtt"]["id"].as<String>();
|
|
||||||
|
|
||||||
LoraConfig lora;
|
|
||||||
lora.frequency = data["lora"]["frequency"].as<long>();
|
|
||||||
lora.spreadingFactor = data["lora"]["spreadingFactor"].as<int>();
|
|
||||||
lora.signalBandwidth = data["lora"]["signalBandwidth"].as<long>();
|
|
||||||
lora.codingRate4 = data["lora"]["codingRate4"].as<int>();
|
|
||||||
lora.power = data["lora"]["power"].as<int>();
|
|
||||||
logConfigInfo(data);
|
|
||||||
configFile.close();
|
|
||||||
|
|
||||||
mqttConfig = mqtt;
|
|
||||||
loraConfig = lora;
|
|
||||||
|
|
||||||
isConfigLoaded = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::writeData()
|
|
||||||
{
|
|
||||||
JsonDocument doc;
|
|
||||||
|
|
||||||
JsonObject mqttJson = doc["mqtt"].to<JsonObject>();
|
|
||||||
mqttJson["server"] = this->mqttConfig.server;
|
|
||||||
mqttJson["port"] = this->mqttConfig.port;
|
|
||||||
mqttJson["username"] = this->mqttConfig.username;
|
|
||||||
mqttJson["password"] = this->mqttConfig.password;
|
|
||||||
mqttJson["id"] = this->mqttConfig.id;
|
|
||||||
mqttJson["topic"] = this->mqttConfig.topic;
|
|
||||||
|
|
||||||
JsonObject lora = doc["lora"].to<JsonObject>();
|
|
||||||
lora["frequency"] = 433775000;
|
|
||||||
lora["spreadingFactor"] = 12;
|
|
||||||
lora["signalBandwidth"] = 125000;
|
|
||||||
lora["codingRate4"] = 5;
|
|
||||||
lora["power"] = 20;
|
|
||||||
|
|
||||||
// Delete existing file, otherwise the configuration is appended to the file
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Write DATA to file");
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Server: " + String(this->mqttConfig.server)).c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Port: " + String(this->mqttConfig.port)).c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Username: " + String(this->mqttConfig.username)).c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Password: " + String(this->mqttConfig.password)).c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("ID: " + String(this->mqttConfig.id)).c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Topic: " + String(this->mqttConfig.topic)).c_str());
|
|
||||||
|
|
||||||
|
|
||||||
SPIFFS.remove(_filePath);
|
|
||||||
File configFile = SPIFFS.open(_filePath.c_str(), "w");
|
|
||||||
if (!configFile)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to open file for writing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize the JSON document to the file
|
|
||||||
if (serializeJson(doc, configFile) == 0)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to write to file");
|
|
||||||
}
|
|
||||||
|
|
||||||
logConfigInfo(doc);
|
|
||||||
// Close the file
|
|
||||||
configFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::logConfigInfo(JsonDocument& doc) {
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Logging configuration data:");
|
|
||||||
|
|
||||||
JsonObject rootJson = doc.as<JsonObject>();
|
|
||||||
|
|
||||||
// Iterate over each key-value pair at the root level
|
|
||||||
for (auto kvp : rootJson) {
|
|
||||||
String key = kvp.key().c_str();
|
|
||||||
String value;
|
|
||||||
|
|
||||||
// Get the value associated with the key
|
|
||||||
const JsonVariant& jsonValue = kvp.value();
|
|
||||||
|
|
||||||
// Check the type of the JSON value and convert it to a string accordingly
|
|
||||||
if (jsonValue.is<String>()) {
|
|
||||||
value = jsonValue.as<String>();
|
|
||||||
} else if (jsonValue.is<int>()) {
|
|
||||||
value = String(jsonValue.as<int>());
|
|
||||||
} else if (jsonValue.is<long>()) {
|
|
||||||
value = String(jsonValue.as<long>());
|
|
||||||
} else if (jsonValue.is<bool>()) {
|
|
||||||
value = jsonValue.as<bool>() ? "true" : "false";
|
|
||||||
} else if (jsonValue.is<JsonArray>() || jsonValue.is<JsonObject>()) {
|
|
||||||
JsonDocument tempJson;
|
|
||||||
tempJson.set(jsonValue);
|
|
||||||
serializeJson(tempJson, value);
|
|
||||||
} else if (jsonValue.isNull()) {
|
|
||||||
value = "null";
|
|
||||||
} else {
|
|
||||||
value = "Unsupported data type";
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", (key + ": " + value).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MqttConfig::setMqtt(const String &server, const int &port, const String &username, const String &password, const String &topic)
|
|
||||||
{
|
|
||||||
this->server = server;
|
|
||||||
this->port = port;
|
|
||||||
this->username = username;
|
|
||||||
this->password = password;
|
|
||||||
this->topic = topic;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MqttConfig::setId(const String &id)
|
|
||||||
{
|
|
||||||
this->id = id;
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
#ifndef CONFIG_H
|
|
||||||
#define CONFIG_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <FS.h>
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
class MqttConfig {
|
|
||||||
public:
|
|
||||||
String server;
|
|
||||||
int port;
|
|
||||||
String username;
|
|
||||||
String password;
|
|
||||||
String id;
|
|
||||||
String topic;
|
|
||||||
void setId(const String& id);
|
|
||||||
void setMqtt(const String& server, const int& port, const String& username, const String& password, const String& topic);
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoraConfig {
|
|
||||||
public:
|
|
||||||
long frequency;
|
|
||||||
int spreadingFactor;
|
|
||||||
long signalBandwidth;
|
|
||||||
int codingRate4;
|
|
||||||
int power;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Config {
|
|
||||||
public:
|
|
||||||
bool isConfigLoaded = false;
|
|
||||||
MqttConfig mqttConfig;
|
|
||||||
LoraConfig loraConfig;
|
|
||||||
Config();
|
|
||||||
void writeData();
|
|
||||||
void setMqttConfig(const String& server, const int& port, const String& username, const String& password, const String& topic) {
|
|
||||||
mqttConfig.setMqtt(server, port, username, password, topic);
|
|
||||||
}
|
|
||||||
void setMqttId(const String& id){
|
|
||||||
mqttConfig.setId(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void logConfigInfo(JsonDocument& configJson);
|
|
||||||
private:
|
|
||||||
void readFile(fs::FS &fs, const char *fileName);
|
|
||||||
String _filePath;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
#include "display.hpp"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
|
|
||||||
// Constructor to initialize the display with I2C parameters
|
|
||||||
Display::Display()
|
|
||||||
: display(DISPLAY_ADDRESS, DISPLAY_SDA, DISPLAY_SCL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::setup_display()
|
|
||||||
{
|
|
||||||
pinMode(16, OUTPUT);
|
|
||||||
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
|
|
||||||
delay(50);
|
|
||||||
digitalWrite(16, HIGH);
|
|
||||||
if (!display.init())
|
|
||||||
{
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "DISPLAY", "Display initialization failed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
display.flipScreenVertically();
|
|
||||||
display.setFont(ArialMT_Plain_10);
|
|
||||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "Display init done!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::display_toggle(bool toggle)
|
|
||||||
{
|
|
||||||
displayOn = toggle;
|
|
||||||
if (displayOn)
|
|
||||||
{
|
|
||||||
display.displayOn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
display.displayOff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::cleanTFT()
|
|
||||||
{
|
|
||||||
display.clear();
|
|
||||||
display.display();
|
|
||||||
display.setFont(ArialMT_Plain_10);
|
|
||||||
}
|
|
||||||
void Display::show_display(String header, int wait)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "One line: %s", header.c_str());
|
|
||||||
cleanTFT();
|
|
||||||
display.setFont(ArialMT_Plain_24);
|
|
||||||
display.drawString(0, 20, header);
|
|
||||||
display.display();
|
|
||||||
delay(wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::show_display(String header, String line1, int wait)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "Two lines: \n %s, \n %s", header.c_str(), line1.c_str());
|
|
||||||
cleanTFT();
|
|
||||||
display.setFont(ArialMT_Plain_16);
|
|
||||||
display.drawString(0, 0, header);
|
|
||||||
display.drawString(0, 18, line1);
|
|
||||||
display.display();
|
|
||||||
delay(wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::show_display(String header, String line1, String line2, int wait)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "Three lines: %s, %s, %s", header.c_str(), line1.c_str(), line2.c_str());
|
|
||||||
cleanTFT();
|
|
||||||
display.drawString(0, 0, header);
|
|
||||||
display.drawString(0, 12, line1);
|
|
||||||
display.drawString(0, 24, line2);
|
|
||||||
display.display();
|
|
||||||
delay(wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::show_display(String header, String line1, String line2, String line3, int wait)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "Four lines: %s, %s, %s, %s", header.c_str(), line1.c_str(), line2.c_str(), line3.c_str());
|
|
||||||
cleanTFT();
|
|
||||||
display.drawString(0, 0, header);
|
|
||||||
display.drawString(0, 12, line1);
|
|
||||||
display.drawString(0, 24, line2);
|
|
||||||
display.drawString(0, 36, line3);
|
|
||||||
display.display();
|
|
||||||
delay(wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::show_display(String header, String line1, String line2, String line3, String line4, int wait)
|
|
||||||
{
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "Five lines: %s, %s, %s, %s, %s", header.c_str(), line1.c_str(), line2.c_str(), line3.c_str(), line4.c_str());
|
|
||||||
cleanTFT();
|
|
||||||
display.drawString(0, 0, header);
|
|
||||||
display.drawString(0, 12, line1);
|
|
||||||
display.drawString(0, 24, line2);
|
|
||||||
display.drawString(0, 36, line3);
|
|
||||||
display.drawString(0, 48, line4);
|
|
||||||
display.display();
|
|
||||||
delay(wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::show_message(const char *message, int line, int wait)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "DISPLAY", "Line %d: %s", line, message);
|
|
||||||
|
|
||||||
display.setFont(ArialMT_Plain_10);
|
|
||||||
|
|
||||||
// Set cursor position based on line number (optional)
|
|
||||||
if (line >= 0 || line <= 5)
|
|
||||||
{
|
|
||||||
display.drawString(0, line * 13, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display the updated content
|
|
||||||
display.display();
|
|
||||||
|
|
||||||
delay(wait); // Convert wait time to milliseconds
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#ifndef DISPLAY_H
|
|
||||||
#define DISPLAY_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
//#include <SSD1306.h>
|
|
||||||
#include "SSD1306Wire.h"
|
|
||||||
#define DISPLAY_ADDRESS 0x3c // CS --> NSS
|
|
||||||
#define DISPLAY_SDA 4
|
|
||||||
#define DISPLAY_SCL 15 // IRQ --> DIO0
|
|
||||||
|
|
||||||
|
|
||||||
class Display {
|
|
||||||
public:
|
|
||||||
Display();
|
|
||||||
|
|
||||||
void setup_display();
|
|
||||||
void display_toggle(bool toggle);
|
|
||||||
void cleanTFT();
|
|
||||||
|
|
||||||
void show_display(String header, int wait = 0);
|
|
||||||
void show_display(String header, String line1, int wait = 0);
|
|
||||||
void show_display(String header, String line1, String line2, int wait = 0);
|
|
||||||
void show_display(String header, String line1, String line2, String line3, int wait = 0);
|
|
||||||
void show_display(String header, String line1, String line2, String line3, String line4, int wait = 0);
|
|
||||||
void show_message(const char* message, int line = 0, int wait = 0);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SSD1306Wire display;
|
|
||||||
bool displayOn;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* DISPLAY_H */
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
#include "config.hpp"
|
|
||||||
#include "lorahandler.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
extern Config config;
|
|
||||||
|
|
||||||
void LoraHandler::setup()
|
|
||||||
{
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "Set SPI pins!");
|
|
||||||
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
|
||||||
LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ);
|
|
||||||
|
|
||||||
long freq = config.loraConfig.frequency;
|
|
||||||
if (!LoRa.begin(freq))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "Starting LoRa failed!");
|
|
||||||
// show_display("ERROR", "Starting LoRa failed!");
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoRa.setSpreadingFactor(config.loraConfig.spreadingFactor);
|
|
||||||
LoRa.setSignalBandwidth(config.loraConfig.signalBandwidth);
|
|
||||||
LoRa.setCodingRate4(config.loraConfig.codingRate4);
|
|
||||||
LoRa.enableCrc();
|
|
||||||
LoRa.setTxPower(config.loraConfig.power);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "LoRa init done!");
|
|
||||||
String currentLoRainfo = "LoRa Freq: " + String(config.loraConfig.frequency) + " / SF:" + String(config.loraConfig.spreadingFactor) + " / CR: " + String(config.loraConfig.codingRate4);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", currentLoRainfo.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceivedLoRaPacket LoraHandler::receivePacket()
|
|
||||||
{
|
|
||||||
ReceivedLoRaPacket receivedLoraPacket;
|
|
||||||
String packet = "";
|
|
||||||
int packetSize = LoRa.parsePacket();
|
|
||||||
if (packetSize)
|
|
||||||
{
|
|
||||||
while (LoRa.available())
|
|
||||||
{
|
|
||||||
int inChar = LoRa.read();
|
|
||||||
packet += (char)inChar;
|
|
||||||
}
|
|
||||||
receivedLoraPacket.text = packet;
|
|
||||||
receivedLoraPacket.rssi = LoRa.packetRssi();
|
|
||||||
receivedLoraPacket.snr = LoRa.packetSnr();
|
|
||||||
receivedLoraPacket.freqError = LoRa.packetFrequencyError();
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Rx", "---> %s", packet.c_str());
|
|
||||||
}
|
|
||||||
return receivedLoraPacket;
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef LORAHANDLER_H
|
|
||||||
#define LORAHANDLER_H
|
|
||||||
|
|
||||||
#include "config.hpp"
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <LoRa.h>
|
|
||||||
|
|
||||||
#define LORA_SCK 5
|
|
||||||
#define LORA_MISO 19
|
|
||||||
#define LORA_MOSI 27
|
|
||||||
#define LORA_CS 18 // CS --> NSS
|
|
||||||
#define LORA_RST 14
|
|
||||||
#define LORA_IRQ 26 // IRQ --> DIO0
|
|
||||||
|
|
||||||
struct ReceivedLoRaPacket {
|
|
||||||
String text;
|
|
||||||
int rssi;
|
|
||||||
float snr;
|
|
||||||
int freqError;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoraHandler {
|
|
||||||
public:
|
|
||||||
void setup();
|
|
||||||
ReceivedLoRaPacket receivePacket();
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LORAHANDLER_H */
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
|
|
||||||
#include <logger.h>
|
|
||||||
#include "wifi.hpp"
|
|
||||||
#include "mqtt.hpp"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "lorahandler.hpp"
|
|
||||||
#include "display.hpp"
|
|
||||||
#include <WiFi.h>
|
|
||||||
|
|
||||||
Config config;
|
|
||||||
WiFiServer server(80);
|
|
||||||
WiFiClient wclient;
|
|
||||||
Mqtt mqtt(wclient);
|
|
||||||
LoraHandler lora;
|
|
||||||
Display display;
|
|
||||||
logging::Logger logger;
|
|
||||||
|
|
||||||
#define TRIGGER_PIN 0
|
|
||||||
void checkButton();
|
|
||||||
|
|
||||||
bool portalRunning = false;
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
Serial.begin(115200);
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
logger.setDebugLevel(logging::LoggerLevel::LOGGER_LEVEL_INFO);
|
|
||||||
#endif
|
|
||||||
pinMode(TRIGGER_PIN, INPUT);
|
|
||||||
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
config = Config();
|
|
||||||
|
|
||||||
while (!config.isConfigLoaded)
|
|
||||||
{
|
|
||||||
delay(10);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MAIN", "COnfig not loaded yet...");
|
|
||||||
}
|
|
||||||
delay(100);
|
|
||||||
display.setup_display();
|
|
||||||
display.show_display("STARTUP");
|
|
||||||
setupWifi("island_temp", false);
|
|
||||||
|
|
||||||
mqtt.mqttSetup();
|
|
||||||
lora.setup();
|
|
||||||
delay(5*1000); // Show text in 5s
|
|
||||||
display.cleanTFT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
ReceivedLoRaPacket packet = lora.receivePacket();
|
|
||||||
if (packet.text.isEmpty())
|
|
||||||
{
|
|
||||||
packet.rssi = 69;
|
|
||||||
packet.snr = 3.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WiFi.status() == WL_CONNECTED) { // Check WiFi connection
|
|
||||||
IPAddress ip = WiFi.localIP();
|
|
||||||
String line0 = "IP: " + ip.toString();
|
|
||||||
display.show_message(line0.c_str(), 0);
|
|
||||||
} else {
|
|
||||||
// Optional: Display message indicating WiFi not connected
|
|
||||||
display.show_message("WiFi not connected", 0);
|
|
||||||
}
|
|
||||||
int mqtt_pkt = 123455;
|
|
||||||
String line1 = "Mqtt pkt: " + String(mqtt_pkt);
|
|
||||||
display.show_message(line1.c_str(), 1);
|
|
||||||
|
|
||||||
String line2 = "Last lora, rssi: " + String(packet.rssi ) ;
|
|
||||||
display.show_message(line2.c_str(), 2);
|
|
||||||
display.show_message("Fourth", 3);
|
|
||||||
display.show_message("Fifth", 4);
|
|
||||||
sleep(5);
|
|
||||||
/*
|
|
||||||
mqtt.mqttRun();
|
|
||||||
if (portalRunning)
|
|
||||||
{
|
|
||||||
wm.process();
|
|
||||||
}
|
|
||||||
mqtt.mqttPublish("test/sensor", "123");
|
|
||||||
checkButton();
|
|
||||||
sleep(10);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkButton()
|
|
||||||
{
|
|
||||||
// check for button press
|
|
||||||
if (digitalRead(TRIGGER_PIN) == LOW)
|
|
||||||
{
|
|
||||||
// poor mans debounce/press-hold, code not ideal for production
|
|
||||||
delay(50);
|
|
||||||
if (digitalRead(TRIGGER_PIN) == LOW)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Button Pressed once, wait 3s");
|
|
||||||
// still holding button for 3000 ms
|
|
||||||
delay(3000); // reset delay hold
|
|
||||||
if (digitalRead(TRIGGER_PIN) == LOW)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Button Pressed, Starting Portal");
|
|
||||||
wm.startWebPortal();
|
|
||||||
portalRunning = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start portal w delay
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Starting config portal");
|
|
||||||
Serial.println("Starting config portal");
|
|
||||||
wm.setConfigPortalTimeout(120);
|
|
||||||
|
|
||||||
if (!wm.startConfigPortal("island_temp"))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "failed to connect or hit timeout");
|
|
||||||
delay(3000);
|
|
||||||
// ESP.restart();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if you get here you have connected to the WiFi
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "connected...yeey :)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
#include "mqtt.hpp"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include <PubSubClient.h>
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
|
|
||||||
extern Config config;
|
|
||||||
extern Config config;
|
|
||||||
|
|
||||||
Mqtt::Mqtt(WiFiClient& wifiClient) : mqttClient(wifiClient) {}
|
|
||||||
|
|
||||||
void Mqtt::mqttSetup()
|
|
||||||
{
|
|
||||||
String message = "MqttServer: " + config.mqttConfig.server + ", MqttPort: " + config.mqttConfig.port;
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
|
||||||
if (config.mqttConfig.server.length() > 0)
|
|
||||||
{
|
|
||||||
// strcpy(mqttHost, config.mqtt.server.c_str());
|
|
||||||
String message = "MqttServer: " + config.mqttConfig.server + ", MqttPort: " + config.mqttConfig.port;
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
|
||||||
IPAddress mqttServerIP;
|
|
||||||
if(mqttServerIP.fromString(config.mqttConfig.server)){
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", mqttServerIP.toString().c_str());
|
|
||||||
mqttClient.setServer(mqttServerIP, config.mqttConfig.port);
|
|
||||||
}else{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "MQTT Invalid IP address format %s", config.mqttConfig.server);
|
|
||||||
}
|
|
||||||
mqttClient.setCallback(callback);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "MQTT config is not set");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mqtt::mqttRun()
|
|
||||||
{
|
|
||||||
delay(100);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "MQTT RUN");
|
|
||||||
if (WiFi.status() == WL_CONNECTED && !mqttClient.loop()) {
|
|
||||||
mqttReconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mqtt::mqttReconnect()
|
|
||||||
{
|
|
||||||
int retryCount = 0;
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Attempting MQTT connection...");
|
|
||||||
// Loop until we're reconnected
|
|
||||||
|
|
||||||
while (!mqttClient.connected() && retryCount < 10)
|
|
||||||
{
|
|
||||||
// Attempt to connect
|
|
||||||
String mqttId = config.mqttConfig.id;
|
|
||||||
if (mqttId.isEmpty())
|
|
||||||
{
|
|
||||||
mqttId = "ESP32-";
|
|
||||||
mqttId += String(random(0xffff), HEX);
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Set ID: %s", mqttId );
|
|
||||||
config.setMqttId(mqttId);
|
|
||||||
config.writeData();
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Server: %s", config.mqttConfig.server.c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Port: %d", config.mqttConfig.port);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Username: %s", config.mqttConfig.username.c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Password: %s", config.mqttConfig.password.c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "ID: %s", config.mqttConfig.id.c_str());
|
|
||||||
|
|
||||||
if (mqttClient.connect(mqttId.c_str(), "simon", "bajsa123"))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "connected");
|
|
||||||
String topic = config.mqttConfig.topic;
|
|
||||||
if (topic.isEmpty())
|
|
||||||
{
|
|
||||||
topic = config.mqttConfig.id;
|
|
||||||
}
|
|
||||||
mqttClient.subscribe(topic.c_str());
|
|
||||||
String message = "Subscribe to: " + topic;
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "MQTT", "Not connected to mqtt, try again in 5 s.");
|
|
||||||
// Wait 5 seconds before retrying
|
|
||||||
delay(5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if we're connected after the loop
|
|
||||||
if (!mqttClient.connected()) {
|
|
||||||
// Connection failed after maximum retries
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to connect to MQTT broker after 10 retries");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mqtt::callback(char *topic, uint8_t *payload, unsigned int length)
|
|
||||||
// Not implemented yet. Just for debug
|
|
||||||
{
|
|
||||||
// Create spot in memory for message
|
|
||||||
char message[length + 1];
|
|
||||||
// Write payload to String
|
|
||||||
strncpy(message, (char *)payload, length);
|
|
||||||
// Nullify last character to eliminate garbage at end
|
|
||||||
message[length] = '\0';
|
|
||||||
|
|
||||||
// Create correct object
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Received: %s", message);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "From: %s", topic);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mqtt::mqttPublish(const char* topic, const char* payload){
|
|
||||||
if (mqttClient.connected()) {
|
|
||||||
mqttClient.publish(topic, payload);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Published message to %s: %s", topic, payload);
|
|
||||||
} else {
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to publish message. MQTT client not connected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#ifndef MQTT_H
|
|
||||||
#define MQTT_H
|
|
||||||
|
|
||||||
#include "wifi.hpp"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include <PubSubClient.h>
|
|
||||||
|
|
||||||
|
|
||||||
class Mqtt {
|
|
||||||
public:
|
|
||||||
Mqtt(WiFiClient& wifiClient);
|
|
||||||
void mqttSetup();
|
|
||||||
void mqttRun();
|
|
||||||
void mqttPublish(const char* topic, const char* payload);
|
|
||||||
private:
|
|
||||||
void mqttReconnect();
|
|
||||||
static void callback(char *topic, uint8_t *payload, unsigned int length);
|
|
||||||
PubSubClient mqttClient;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* MQTT_H */
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
#include "wifi.hpp"
|
|
||||||
#include <logger.h>
|
|
||||||
|
|
||||||
WiFiManager wm;
|
|
||||||
extern Config config;
|
|
||||||
extern logging::Logger logger;
|
|
||||||
// Flag for saving data
|
|
||||||
bool shouldSaveConfig = false;
|
|
||||||
|
|
||||||
// Variables to hold data from custom textboxes
|
|
||||||
char testString[50] = "test value";
|
|
||||||
int testNumber = 1234;
|
|
||||||
char mqtt_server[40];
|
|
||||||
int mqtt_port = 1883;
|
|
||||||
char mqtt_username[34] = "";
|
|
||||||
char mqtt_password[34] = "";
|
|
||||||
char mqtt_topic[34] = "";
|
|
||||||
|
|
||||||
void setupWifi(const char *setupWifi, bool resetOnStart)
|
|
||||||
{
|
|
||||||
// Change to true when testing to force configuration every time we run
|
|
||||||
bool forceConfig = false;
|
|
||||||
wm.setConfigPortalTimeout(60);
|
|
||||||
// Reset settings (only for development)
|
|
||||||
if (resetOnStart)
|
|
||||||
{
|
|
||||||
wm.resetSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set config save notify callback
|
|
||||||
wm.setSaveConfigCallback(saveConfigCallback);
|
|
||||||
|
|
||||||
// Set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
|
|
||||||
wm.setAPCallback(configModeCallback);
|
|
||||||
|
|
||||||
// Custom elements
|
|
||||||
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
|
|
||||||
WiFiManagerParameter custom_mqtt_username("username", "mqtt username", mqtt_username, 50);
|
|
||||||
WiFiManagerParameter custom_mqtt_password("password", "mqtt password", mqtt_password, 50);
|
|
||||||
WiFiManagerParameter custom_mqtt_topic("topic", "mqtt topic", mqtt_topic, 50);
|
|
||||||
|
|
||||||
// Text box (String) - 50 characters maximum
|
|
||||||
WiFiManagerParameter custom_text_box("key_text", "Enter your string here", testString, 50);
|
|
||||||
|
|
||||||
// Need to convert numerical input to string to display the default value.
|
|
||||||
char convertedValue[6];
|
|
||||||
sprintf(convertedValue, "%d", testNumber);
|
|
||||||
|
|
||||||
// Text box (Number) - 7 characters maximum
|
|
||||||
WiFiManagerParameter custom_text_box_num("key_num", "Enter your number here", convertedValue, 7);
|
|
||||||
char convertedMqttPort[6];
|
|
||||||
sprintf(convertedMqttPort, "%d", mqtt_port);
|
|
||||||
WiFiManagerParameter custom_mqtt_port("port", "mqtt port", convertedMqttPort, 6);
|
|
||||||
|
|
||||||
// Add all defined parameters
|
|
||||||
wm.addParameter(&custom_text_box);
|
|
||||||
wm.addParameter(&custom_text_box_num);
|
|
||||||
wm.addParameter(&custom_mqtt_server);
|
|
||||||
wm.addParameter(&custom_mqtt_port);
|
|
||||||
wm.addParameter(&custom_mqtt_username);
|
|
||||||
wm.addParameter(&custom_mqtt_password);
|
|
||||||
wm.addParameter(&custom_mqtt_topic);
|
|
||||||
|
|
||||||
if (forceConfig)
|
|
||||||
// Run if we need a configuration
|
|
||||||
{
|
|
||||||
if (!wm.startConfigPortal(setupWifi))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Wifi", "failed to connect and hit timeout");
|
|
||||||
delay(3000);
|
|
||||||
// reset and try again, or maybe put it to deep sleep
|
|
||||||
ESP.restart();
|
|
||||||
delay(5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!wm.autoConnect(setupWifi))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Wifi", "failed to connect and hit timeout");
|
|
||||||
delay(3000);
|
|
||||||
// if we still have not connected restart and try all over again
|
|
||||||
ESP.restart();
|
|
||||||
delay(5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here, we are connected to the WiFi
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "");
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "WiFi connected");
|
|
||||||
String message = "IP address: " + String(WiFi.localIP());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
|
|
||||||
|
|
||||||
// Lets deal with the user config values
|
|
||||||
|
|
||||||
// Copy the string value
|
|
||||||
strncpy(testString, custom_text_box.getValue(), sizeof(testString));
|
|
||||||
Serial.print("testString: ");
|
|
||||||
Serial.println(testString);
|
|
||||||
|
|
||||||
// Convert the number value
|
|
||||||
testNumber = atoi(custom_text_box_num.getValue());
|
|
||||||
Serial.print("testNumber: ");
|
|
||||||
Serial.println(testNumber);
|
|
||||||
|
|
||||||
mqtt_port = atoi(custom_mqtt_port.getValue());
|
|
||||||
strncpy(mqtt_server, custom_mqtt_server.getValue(), sizeof(mqtt_server));
|
|
||||||
strncpy(mqtt_username, custom_mqtt_username.getValue(), sizeof(mqtt_username));
|
|
||||||
strncpy(mqtt_password, custom_mqtt_password.getValue(), sizeof(mqtt_password));
|
|
||||||
strncpy(mqtt_topic, custom_mqtt_topic.getValue(), sizeof(mqtt_topic));
|
|
||||||
|
|
||||||
|
|
||||||
// Save the custom parameters to FS
|
|
||||||
if (shouldSaveConfig)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Save config");
|
|
||||||
saveConfigFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void saveConfigCallback()
|
|
||||||
// Callback notifying us of the need to save configuration
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Should save config");
|
|
||||||
shouldSaveConfig = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void configModeCallback(WiFiManager *myWiFiManager)
|
|
||||||
// Called when config mode launched
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Entered Configuration Mode");
|
|
||||||
|
|
||||||
String message = "Config SSID: " + String(myWiFiManager->getConfigPortalSSID());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
|
|
||||||
|
|
||||||
|
|
||||||
message = "Config IP Address: " + String(WiFi.softAPIP());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void saveConfigFile()
|
|
||||||
// Save Config in JSON format
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Saving configuration...");
|
|
||||||
config.setMqttConfig(mqtt_server, mqtt_port, mqtt_username, mqtt_password, mqtt_topic);
|
|
||||||
config.writeData();
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef WIFI_H
|
|
||||||
#define WIFI_H
|
|
||||||
|
|
||||||
// File System Library
|
|
||||||
#include <FS.h>
|
|
||||||
// SPI Flash Syetem Library
|
|
||||||
#include <SPIFFS.h>
|
|
||||||
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include "config.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
extern WiFiManager wm;
|
|
||||||
|
|
||||||
// Flag for saving data
|
|
||||||
extern bool shouldSaveConfig;
|
|
||||||
|
|
||||||
|
|
||||||
void setupWifi(const char *apName, bool resetOnStart);
|
|
||||||
void saveConfigCallback();
|
|
||||||
void configModeCallback(WiFiManager *myWiFiManager);
|
|
||||||
bool loadConfigFile();
|
|
||||||
void saveConfigFile();
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* WIFI_H */
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
|
@ -1,315 +0,0 @@
|
||||||
(footprint "LilyGO_T5_2.13_V2.3"
|
|
||||||
(version 20241229)
|
|
||||||
(generator "pcbnew")
|
|
||||||
(generator_version "9.0")
|
|
||||||
(layer "F.Cu")
|
|
||||||
(descr "Footprint for LilyGO T5 2.13 V2.3 e-paper module")
|
|
||||||
(tags "LilyGO T5 e-paper")
|
|
||||||
(property "Reference" "REF**"
|
|
||||||
(at 1.27 -37.6 0)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "2eb68159-2f43-4e2b-a754-310864418cce")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(property "Value" "LilyGO_T5_2.13"
|
|
||||||
(at 10 -10 0)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(uuid "6c908391-4387-4b76-ae85-321cce059780")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(property "Datasheet" ""
|
|
||||||
(at 1.27 -16.51 0)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(hide yes)
|
|
||||||
(uuid "4a68447e-20bc-4125-b639-8f458329ed17")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1.27 1.27)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(property "Description" ""
|
|
||||||
(at 1.27 -16.51 0)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(hide yes)
|
|
||||||
(uuid "8043e483-8f19-4aba-a4d9-5939616e0de9")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1.27 1.27)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(attr through_hole)
|
|
||||||
(fp_line
|
|
||||||
(start 0 -66.29)
|
|
||||||
(end 36.35 -66.29)
|
|
||||||
(stroke
|
|
||||||
(width 0.12)
|
|
||||||
(type solid)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "e5210833-f708-411c-84db-98902b353473")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start 0 0)
|
|
||||||
(end 0 -66.29)
|
|
||||||
(stroke
|
|
||||||
(width 0.12)
|
|
||||||
(type solid)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "f5975bc1-2665-4b16-8fec-43baaf338d14")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start 36.35 -66.29)
|
|
||||||
(end 36.35 0)
|
|
||||||
(stroke
|
|
||||||
(width 0.12)
|
|
||||||
(type solid)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "a043b2d7-a9f5-43b8-ae4f-df7bdc84d005")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start 36.35 0)
|
|
||||||
(end 0 0)
|
|
||||||
(stroke
|
|
||||||
(width 0.12)
|
|
||||||
(type solid)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "0b56b776-f073-4bf6-9ad5-854b39e4778a")
|
|
||||||
)
|
|
||||||
(fp_rect
|
|
||||||
(start 0 -66.29)
|
|
||||||
(end 36.35 0)
|
|
||||||
(stroke
|
|
||||||
(width 0.05)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(fill no)
|
|
||||||
(layer "F.CrtYd")
|
|
||||||
(uuid "a2044ea7-61aa-4787-80be-82b519e322ee")
|
|
||||||
)
|
|
||||||
(pad "1" thru_hole rect
|
|
||||||
(at 1.27 -32.6)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "e6845e72-5998-4306-a024-9276fd5f1ad5")
|
|
||||||
)
|
|
||||||
(pad "2" thru_hole rect
|
|
||||||
(at 1.27 -35.14)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "37207e8a-a869-4bf7-9477-6f1d87a3b321")
|
|
||||||
)
|
|
||||||
(pad "3" thru_hole rect
|
|
||||||
(at 1.27 -37.68)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "0af65940-aa93-4c60-a852-bb45e9d5e76c")
|
|
||||||
)
|
|
||||||
(pad "4" thru_hole rect
|
|
||||||
(at 1.27 -40.22)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "caacd5f6-6871-491f-aa32-3e2b4a778b34")
|
|
||||||
)
|
|
||||||
(pad "5" thru_hole rect
|
|
||||||
(at 1.27 -42.76)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "11e76bf1-e9d5-4d91-a623-0bbfd21c48f7")
|
|
||||||
)
|
|
||||||
(pad "6" thru_hole rect
|
|
||||||
(at 1.27 -45.3)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "883035b8-b5b0-4e13-8af9-3d9f4a5e4d2c")
|
|
||||||
)
|
|
||||||
(pad "7" thru_hole rect
|
|
||||||
(at 1.27 -47.84)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "ea2c5f3c-f803-4907-b690-3fb78abd768e")
|
|
||||||
)
|
|
||||||
(pad "8" thru_hole rect
|
|
||||||
(at 1.27 -50.38)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "db6ecdec-fb70-4e5f-9d44-e4530501f83d")
|
|
||||||
)
|
|
||||||
(pad "9" thru_hole rect
|
|
||||||
(at 1.27 -52.92)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "52df1fa0-6332-451a-b6ae-745b6323a1a3")
|
|
||||||
)
|
|
||||||
(pad "10" thru_hole rect
|
|
||||||
(at 1.27 -55.46)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "f7c3f3c9-c6c5-4377-9f06-1a7ce0f65690")
|
|
||||||
)
|
|
||||||
(pad "11" thru_hole rect
|
|
||||||
(at 1.27 -58)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "861104ac-78a7-47df-95cc-4b026abe2fd7")
|
|
||||||
)
|
|
||||||
(pad "12" thru_hole rect
|
|
||||||
(at 1.27 -60.54)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "8799d0d2-4f41-4353-b01c-cd4c7c414144")
|
|
||||||
)
|
|
||||||
(pad "13" thru_hole rect
|
|
||||||
(at 1.27 -63.08)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "2532904b-396d-4fe4-9350-768ca406f153")
|
|
||||||
)
|
|
||||||
(pad "14" thru_hole circle
|
|
||||||
(at 33.5 -32.68)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "1fe1915d-aeca-47c0-a8bc-b6aa57a1192c")
|
|
||||||
)
|
|
||||||
(pad "15" thru_hole circle
|
|
||||||
(at 33.5 -35.22)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "b1eeaad9-1cf0-43a8-b301-6d125ed7766f")
|
|
||||||
)
|
|
||||||
(pad "16" thru_hole circle
|
|
||||||
(at 33.5 -37.76)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "b5772389-9314-4992-a362-5e19a3d5573a")
|
|
||||||
)
|
|
||||||
(pad "17" thru_hole circle
|
|
||||||
(at 33.5 -40.3)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "186630c9-c5d1-4a64-8359-8b0e3bbdc45d")
|
|
||||||
)
|
|
||||||
(pad "18" thru_hole circle
|
|
||||||
(at 33.5 -42.84)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "380413e1-fbbc-453d-bcc5-7632b249fe7f")
|
|
||||||
)
|
|
||||||
(pad "19" thru_hole circle
|
|
||||||
(at 33.5 -45.38)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "d76f48db-a08d-4003-9c61-4a5e38fbff73")
|
|
||||||
)
|
|
||||||
(pad "20" thru_hole circle
|
|
||||||
(at 33.5 -47.92)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "6dee520c-4d6b-4e0b-b2e9-c34f433653f1")
|
|
||||||
)
|
|
||||||
(pad "21" thru_hole circle
|
|
||||||
(at 33.5 -50.46)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "76b9ca8d-a3eb-49ea-9c09-e59d5a04bf27")
|
|
||||||
)
|
|
||||||
(pad "22" thru_hole circle
|
|
||||||
(at 33.5 -53)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "d5fb5aaf-a7a7-4b30-bc70-c77b5eb47f97")
|
|
||||||
)
|
|
||||||
(pad "23" thru_hole circle
|
|
||||||
(at 33.5 -55.54)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "34924216-c3b4-4231-ba37-1e5648dfd6a0")
|
|
||||||
)
|
|
||||||
(pad "24" thru_hole circle
|
|
||||||
(at 33.5 -58.08)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "7e7f50b0-0a7f-49f4-b82f-c5d736f416e5")
|
|
||||||
)
|
|
||||||
(pad "25" thru_hole circle
|
|
||||||
(at 33.5 -60.62)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "d9db3d97-2265-4b8c-8b68-62232c907e68")
|
|
||||||
)
|
|
||||||
(pad "26" thru_hole circle
|
|
||||||
(at 33.5 -63.16)
|
|
||||||
(size 1.5 1.5)
|
|
||||||
(drill 0.8)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "4ac0d3d2-1c70-4fe4-a676-0c4c7cd4a072")
|
|
||||||
)
|
|
||||||
(embedded_fonts no)
|
|
||||||
)
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,135 +0,0 @@
|
||||||
{
|
|
||||||
"board": {
|
|
||||||
"active_layer": 0,
|
|
||||||
"active_layer_preset": "All Layers",
|
|
||||||
"auto_track_width": true,
|
|
||||||
"hidden_netclasses": [],
|
|
||||||
"hidden_nets": [],
|
|
||||||
"high_contrast_mode": 1,
|
|
||||||
"net_color_mode": 1,
|
|
||||||
"opacity": {
|
|
||||||
"images": 0.6,
|
|
||||||
"pads": 1.0,
|
|
||||||
"shapes": 1.0,
|
|
||||||
"tracks": 1.0,
|
|
||||||
"vias": 1.0,
|
|
||||||
"zones": 0.6
|
|
||||||
},
|
|
||||||
"prototype_zone_fills": false,
|
|
||||||
"selection_filter": {
|
|
||||||
"dimensions": true,
|
|
||||||
"footprints": true,
|
|
||||||
"graphics": true,
|
|
||||||
"keepouts": true,
|
|
||||||
"lockedItems": false,
|
|
||||||
"otherItems": true,
|
|
||||||
"pads": true,
|
|
||||||
"text": true,
|
|
||||||
"tracks": true,
|
|
||||||
"vias": true,
|
|
||||||
"zones": true
|
|
||||||
},
|
|
||||||
"visible_items": [
|
|
||||||
"vias",
|
|
||||||
"footprint_text",
|
|
||||||
"footprint_anchors",
|
|
||||||
"ratsnest",
|
|
||||||
"grid",
|
|
||||||
"footprints_front",
|
|
||||||
"footprints_back",
|
|
||||||
"footprint_values",
|
|
||||||
"footprint_references",
|
|
||||||
"tracks",
|
|
||||||
"drc_errors",
|
|
||||||
"drawing_sheet",
|
|
||||||
"bitmaps",
|
|
||||||
"pads",
|
|
||||||
"zones",
|
|
||||||
"drc_warnings",
|
|
||||||
"locked_item_shadows",
|
|
||||||
"conflict_shadows",
|
|
||||||
"shapes"
|
|
||||||
],
|
|
||||||
"visible_layers": "ffffffff_ffffffff_ffffffff_ffffffff",
|
|
||||||
"zone_display_mode": 0
|
|
||||||
},
|
|
||||||
"git": {
|
|
||||||
"integration_disabled": false,
|
|
||||||
"repo_type": "",
|
|
||||||
"repo_username": "",
|
|
||||||
"ssh_key": ""
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"filename": "water_temp.kicad_prl",
|
|
||||||
"version": 5
|
|
||||||
},
|
|
||||||
"net_inspector_panel": {
|
|
||||||
"col_hidden": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"col_order": [
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
5,
|
|
||||||
6,
|
|
||||||
7,
|
|
||||||
8,
|
|
||||||
9
|
|
||||||
],
|
|
||||||
"col_widths": [
|
|
||||||
148,
|
|
||||||
234,
|
|
||||||
91,
|
|
||||||
123,
|
|
||||||
178,
|
|
||||||
207,
|
|
||||||
194,
|
|
||||||
170,
|
|
||||||
91,
|
|
||||||
780
|
|
||||||
],
|
|
||||||
"custom_group_rules": [],
|
|
||||||
"expanded_rows": [],
|
|
||||||
"filter_by_net_name": true,
|
|
||||||
"filter_by_netclass": true,
|
|
||||||
"filter_text": "",
|
|
||||||
"group_by_constraint": false,
|
|
||||||
"group_by_netclass": false,
|
|
||||||
"show_time_domain_details": false,
|
|
||||||
"show_unconnected_nets": false,
|
|
||||||
"show_zero_pad_nets": false,
|
|
||||||
"sort_ascending": true,
|
|
||||||
"sorting_column": 1
|
|
||||||
},
|
|
||||||
"open_jobsets": [],
|
|
||||||
"project": {
|
|
||||||
"files": []
|
|
||||||
},
|
|
||||||
"schematic": {
|
|
||||||
"hierarchy_collapsed": [],
|
|
||||||
"selection_filter": {
|
|
||||||
"graphics": true,
|
|
||||||
"images": true,
|
|
||||||
"labels": true,
|
|
||||||
"lockedItems": false,
|
|
||||||
"otherItems": true,
|
|
||||||
"pins": true,
|
|
||||||
"ruleAreas": true,
|
|
||||||
"symbols": true,
|
|
||||||
"text": true,
|
|
||||||
"wires": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,716 +0,0 @@
|
||||||
{
|
|
||||||
"board": {
|
|
||||||
"3dviewports": [],
|
|
||||||
"design_settings": {
|
|
||||||
"defaults": {
|
|
||||||
"apply_defaults_to_fp_fields": false,
|
|
||||||
"apply_defaults_to_fp_shapes": false,
|
|
||||||
"apply_defaults_to_fp_text": false,
|
|
||||||
"board_outline_line_width": 0.05,
|
|
||||||
"copper_line_width": 0.2,
|
|
||||||
"copper_text_italic": false,
|
|
||||||
"copper_text_size_h": 1.5,
|
|
||||||
"copper_text_size_v": 1.5,
|
|
||||||
"copper_text_thickness": 0.3,
|
|
||||||
"copper_text_upright": false,
|
|
||||||
"courtyard_line_width": 0.05,
|
|
||||||
"dimension_precision": 4,
|
|
||||||
"dimension_units": 3,
|
|
||||||
"dimensions": {
|
|
||||||
"arrow_length": 1270000,
|
|
||||||
"extension_offset": 500000,
|
|
||||||
"keep_text_aligned": true,
|
|
||||||
"suppress_zeroes": true,
|
|
||||||
"text_position": 0,
|
|
||||||
"units_format": 0
|
|
||||||
},
|
|
||||||
"fab_line_width": 0.1,
|
|
||||||
"fab_text_italic": false,
|
|
||||||
"fab_text_size_h": 1.0,
|
|
||||||
"fab_text_size_v": 1.0,
|
|
||||||
"fab_text_thickness": 0.15,
|
|
||||||
"fab_text_upright": false,
|
|
||||||
"other_line_width": 0.1,
|
|
||||||
"other_text_italic": false,
|
|
||||||
"other_text_size_h": 1.0,
|
|
||||||
"other_text_size_v": 1.0,
|
|
||||||
"other_text_thickness": 0.15,
|
|
||||||
"other_text_upright": false,
|
|
||||||
"pads": {
|
|
||||||
"drill": 0.8,
|
|
||||||
"height": 1.27,
|
|
||||||
"width": 2.54
|
|
||||||
},
|
|
||||||
"silk_line_width": 0.1,
|
|
||||||
"silk_text_italic": false,
|
|
||||||
"silk_text_size_h": 1.0,
|
|
||||||
"silk_text_size_v": 1.0,
|
|
||||||
"silk_text_thickness": 0.1,
|
|
||||||
"silk_text_upright": false,
|
|
||||||
"zones": {
|
|
||||||
"min_clearance": 0.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"diff_pair_dimensions": [
|
|
||||||
{
|
|
||||||
"gap": 0.0,
|
|
||||||
"via_gap": 0.0,
|
|
||||||
"width": 0.0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"drc_exclusions": [],
|
|
||||||
"meta": {
|
|
||||||
"version": 2
|
|
||||||
},
|
|
||||||
"rule_severities": {
|
|
||||||
"annular_width": "error",
|
|
||||||
"clearance": "error",
|
|
||||||
"connection_width": "warning",
|
|
||||||
"copper_edge_clearance": "error",
|
|
||||||
"copper_sliver": "warning",
|
|
||||||
"courtyards_overlap": "error",
|
|
||||||
"creepage": "error",
|
|
||||||
"diff_pair_gap_out_of_range": "error",
|
|
||||||
"diff_pair_uncoupled_length_too_long": "error",
|
|
||||||
"drill_out_of_range": "error",
|
|
||||||
"duplicate_footprints": "warning",
|
|
||||||
"extra_footprint": "warning",
|
|
||||||
"footprint": "error",
|
|
||||||
"footprint_filters_mismatch": "ignore",
|
|
||||||
"footprint_symbol_mismatch": "warning",
|
|
||||||
"footprint_type_mismatch": "ignore",
|
|
||||||
"hole_clearance": "error",
|
|
||||||
"hole_to_hole": "warning",
|
|
||||||
"holes_co_located": "warning",
|
|
||||||
"invalid_outline": "error",
|
|
||||||
"isolated_copper": "warning",
|
|
||||||
"item_on_disabled_layer": "error",
|
|
||||||
"items_not_allowed": "error",
|
|
||||||
"length_out_of_range": "error",
|
|
||||||
"lib_footprint_issues": "warning",
|
|
||||||
"lib_footprint_mismatch": "warning",
|
|
||||||
"malformed_courtyard": "error",
|
|
||||||
"microvia_drill_out_of_range": "error",
|
|
||||||
"mirrored_text_on_front_layer": "warning",
|
|
||||||
"missing_courtyard": "ignore",
|
|
||||||
"missing_footprint": "warning",
|
|
||||||
"net_conflict": "warning",
|
|
||||||
"nonmirrored_text_on_back_layer": "warning",
|
|
||||||
"npth_inside_courtyard": "ignore",
|
|
||||||
"padstack": "warning",
|
|
||||||
"pth_inside_courtyard": "ignore",
|
|
||||||
"shorting_items": "error",
|
|
||||||
"silk_edge_clearance": "warning",
|
|
||||||
"silk_over_copper": "warning",
|
|
||||||
"silk_overlap": "warning",
|
|
||||||
"skew_out_of_range": "error",
|
|
||||||
"solder_mask_bridge": "error",
|
|
||||||
"starved_thermal": "error",
|
|
||||||
"text_height": "warning",
|
|
||||||
"text_on_edge_cuts": "error",
|
|
||||||
"text_thickness": "warning",
|
|
||||||
"through_hole_pad_without_hole": "error",
|
|
||||||
"too_many_vias": "error",
|
|
||||||
"track_angle": "error",
|
|
||||||
"track_dangling": "warning",
|
|
||||||
"track_segment_length": "error",
|
|
||||||
"track_width": "error",
|
|
||||||
"tracks_crossing": "error",
|
|
||||||
"unconnected_items": "error",
|
|
||||||
"unresolved_variable": "error",
|
|
||||||
"via_dangling": "warning",
|
|
||||||
"zones_intersect": "error"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"max_error": 0.005,
|
|
||||||
"min_clearance": 0.0,
|
|
||||||
"min_connection": 0.0,
|
|
||||||
"min_copper_edge_clearance": 0.5,
|
|
||||||
"min_groove_width": 0.0,
|
|
||||||
"min_hole_clearance": 0.25,
|
|
||||||
"min_hole_to_hole": 0.25,
|
|
||||||
"min_microvia_diameter": 0.2,
|
|
||||||
"min_microvia_drill": 0.1,
|
|
||||||
"min_resolved_spokes": 2,
|
|
||||||
"min_silk_clearance": 0.0,
|
|
||||||
"min_text_height": 0.8,
|
|
||||||
"min_text_thickness": 0.08,
|
|
||||||
"min_through_hole_diameter": 0.3,
|
|
||||||
"min_track_width": 0.0,
|
|
||||||
"min_via_annular_width": 0.1,
|
|
||||||
"min_via_diameter": 0.5,
|
|
||||||
"solder_mask_to_copper_clearance": 0.0,
|
|
||||||
"use_height_for_length_calcs": true
|
|
||||||
},
|
|
||||||
"teardrop_options": [
|
|
||||||
{
|
|
||||||
"td_onpthpad": true,
|
|
||||||
"td_onroundshapesonly": false,
|
|
||||||
"td_onsmdpad": true,
|
|
||||||
"td_ontrackend": false,
|
|
||||||
"td_onvia": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"teardrop_parameters": [
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_round_shape",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_rect_shape",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_track_end",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"track_widths": [
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"tuning_pattern_settings": {
|
|
||||||
"diff_pair_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 1.0
|
|
||||||
},
|
|
||||||
"diff_pair_skew_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 0.6
|
|
||||||
},
|
|
||||||
"single_track_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 0.6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"via_dimensions": [
|
|
||||||
{
|
|
||||||
"diameter": 0.0,
|
|
||||||
"drill": 0.0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"zones_allow_external_fillets": false
|
|
||||||
},
|
|
||||||
"ipc2581": {
|
|
||||||
"bom_rev": "",
|
|
||||||
"dist": "",
|
|
||||||
"distpn": "",
|
|
||||||
"internal_id": "",
|
|
||||||
"mfg": "",
|
|
||||||
"mpn": "",
|
|
||||||
"sch_revision": ""
|
|
||||||
},
|
|
||||||
"layer_pairs": [],
|
|
||||||
"layer_presets": [],
|
|
||||||
"viewports": []
|
|
||||||
},
|
|
||||||
"boards": [],
|
|
||||||
"component_class_settings": {
|
|
||||||
"assignments": [],
|
|
||||||
"meta": {
|
|
||||||
"version": 0
|
|
||||||
},
|
|
||||||
"sheet_component_classes": {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cvpcb": {
|
|
||||||
"equivalence_files": []
|
|
||||||
},
|
|
||||||
"erc": {
|
|
||||||
"erc_exclusions": [],
|
|
||||||
"meta": {
|
|
||||||
"version": 0
|
|
||||||
},
|
|
||||||
"pin_map": [
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"rule_severities": {
|
|
||||||
"bus_definition_conflict": "error",
|
|
||||||
"bus_entry_needed": "error",
|
|
||||||
"bus_to_bus_conflict": "error",
|
|
||||||
"bus_to_net_conflict": "error",
|
|
||||||
"different_unit_footprint": "error",
|
|
||||||
"different_unit_net": "error",
|
|
||||||
"duplicate_reference": "error",
|
|
||||||
"duplicate_sheet_names": "error",
|
|
||||||
"endpoint_off_grid": "warning",
|
|
||||||
"extra_units": "error",
|
|
||||||
"field_name_whitespace": "warning",
|
|
||||||
"footprint_filter": "ignore",
|
|
||||||
"footprint_link_issues": "warning",
|
|
||||||
"four_way_junction": "ignore",
|
|
||||||
"global_label_dangling": "warning",
|
|
||||||
"ground_pin_not_ground": "warning",
|
|
||||||
"hier_label_mismatch": "error",
|
|
||||||
"isolated_pin_label": "warning",
|
|
||||||
"label_dangling": "error",
|
|
||||||
"label_multiple_wires": "warning",
|
|
||||||
"lib_symbol_issues": "warning",
|
|
||||||
"lib_symbol_mismatch": "warning",
|
|
||||||
"missing_bidi_pin": "warning",
|
|
||||||
"missing_input_pin": "warning",
|
|
||||||
"missing_power_pin": "error",
|
|
||||||
"missing_unit": "warning",
|
|
||||||
"multiple_net_names": "warning",
|
|
||||||
"net_not_bus_member": "warning",
|
|
||||||
"no_connect_connected": "warning",
|
|
||||||
"no_connect_dangling": "warning",
|
|
||||||
"pin_not_connected": "error",
|
|
||||||
"pin_not_driven": "error",
|
|
||||||
"pin_to_pin": "warning",
|
|
||||||
"power_pin_not_driven": "error",
|
|
||||||
"same_local_global_label": "warning",
|
|
||||||
"similar_label_and_power": "warning",
|
|
||||||
"similar_labels": "warning",
|
|
||||||
"similar_power": "warning",
|
|
||||||
"simulation_model_issue": "ignore",
|
|
||||||
"single_global_label": "ignore",
|
|
||||||
"stacked_pin_name": "warning",
|
|
||||||
"unannotated": "error",
|
|
||||||
"unconnected_wire_endpoint": "warning",
|
|
||||||
"undefined_netclass": "error",
|
|
||||||
"unit_value_mismatch": "error",
|
|
||||||
"unresolved_variable": "error",
|
|
||||||
"wire_dangling": "error"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libraries": {
|
|
||||||
"pinned_footprint_libs": [
|
|
||||||
"Library"
|
|
||||||
],
|
|
||||||
"pinned_symbol_libs": [
|
|
||||||
"MyKicadLib"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"filename": "water_temp.kicad_pro",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"net_settings": {
|
|
||||||
"classes": [
|
|
||||||
{
|
|
||||||
"bus_width": 12,
|
|
||||||
"clearance": 0.2,
|
|
||||||
"diff_pair_gap": 0.25,
|
|
||||||
"diff_pair_via_gap": 0.25,
|
|
||||||
"diff_pair_width": 0.2,
|
|
||||||
"line_style": 0,
|
|
||||||
"microvia_diameter": 0.3,
|
|
||||||
"microvia_drill": 0.1,
|
|
||||||
"name": "Default",
|
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"priority": 2147483647,
|
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"track_width": 0.25,
|
|
||||||
"tuning_profile": "",
|
|
||||||
"via_diameter": 0.6,
|
|
||||||
"via_drill": 0.3,
|
|
||||||
"wire_width": 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"clearance": 0.3,
|
|
||||||
"diff_pair_gap": 0.25,
|
|
||||||
"diff_pair_width": 0.2,
|
|
||||||
"microvia_diameter": 0.3,
|
|
||||||
"microvia_drill": 0.1,
|
|
||||||
"name": "Power",
|
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"priority": 0,
|
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"track_width": 0.5,
|
|
||||||
"tuning_profile": "",
|
|
||||||
"via_diameter": 0.6,
|
|
||||||
"via_drill": 0.3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"version": 5
|
|
||||||
},
|
|
||||||
"net_colors": {
|
|
||||||
"3v3": "rgb(194, 0, 0)"
|
|
||||||
},
|
|
||||||
"netclass_assignments": null,
|
|
||||||
"netclass_patterns": [
|
|
||||||
{
|
|
||||||
"netclass": "Power",
|
|
||||||
"pattern": "3v3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Power",
|
|
||||||
"pattern": "GND"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Power",
|
|
||||||
"pattern": "V"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"pcbnew": {
|
|
||||||
"last_paths": {
|
|
||||||
"gencad": "",
|
|
||||||
"idf": "",
|
|
||||||
"netlist": "",
|
|
||||||
"plot": "",
|
|
||||||
"pos_files": "",
|
|
||||||
"specctra_dsn": "",
|
|
||||||
"step": "",
|
|
||||||
"svg": "",
|
|
||||||
"vrml": ""
|
|
||||||
},
|
|
||||||
"page_layout_descr_file": ""
|
|
||||||
},
|
|
||||||
"schematic": {
|
|
||||||
"annotate_start_num": 0,
|
|
||||||
"annotation": {
|
|
||||||
"method": 0,
|
|
||||||
"sort_order": 0
|
|
||||||
},
|
|
||||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
|
||||||
"bom_fmt_presets": [],
|
|
||||||
"bom_fmt_settings": {
|
|
||||||
"field_delimiter": ",",
|
|
||||||
"keep_line_breaks": false,
|
|
||||||
"keep_tabs": false,
|
|
||||||
"name": "CSV",
|
|
||||||
"ref_delimiter": ",",
|
|
||||||
"ref_range_delimiter": "",
|
|
||||||
"string_delimiter": "\""
|
|
||||||
},
|
|
||||||
"bom_presets": [],
|
|
||||||
"bom_settings": {
|
|
||||||
"exclude_dnp": false,
|
|
||||||
"fields_ordered": [
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Reference",
|
|
||||||
"name": "Reference",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Qty",
|
|
||||||
"name": "${QUANTITY}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Value",
|
|
||||||
"name": "Value",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "DNP",
|
|
||||||
"name": "${DNP}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Exclude from BOM",
|
|
||||||
"name": "${EXCLUDE_FROM_BOM}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Exclude from Board",
|
|
||||||
"name": "${EXCLUDE_FROM_BOARD}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Footprint",
|
|
||||||
"name": "Footprint",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Datasheet",
|
|
||||||
"name": "Datasheet",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Beskrivning",
|
|
||||||
"name": "Description",
|
|
||||||
"show": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "nr.",
|
|
||||||
"name": "${ITEM_NUMBER}",
|
|
||||||
"show": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filter_string": "",
|
|
||||||
"group_symbols": true,
|
|
||||||
"include_excluded_from_bom": true,
|
|
||||||
"name": "",
|
|
||||||
"sort_asc": true,
|
|
||||||
"sort_field": "Reference"
|
|
||||||
},
|
|
||||||
"bus_aliases": {},
|
|
||||||
"connection_grid_size": 50.0,
|
|
||||||
"drawing": {
|
|
||||||
"dashed_lines_dash_length_ratio": 12.0,
|
|
||||||
"dashed_lines_gap_length_ratio": 3.0,
|
|
||||||
"default_line_thickness": 6.0,
|
|
||||||
"default_text_size": 50.0,
|
|
||||||
"field_names": [],
|
|
||||||
"hop_over_size_choice": 0,
|
|
||||||
"intersheets_ref_own_page": false,
|
|
||||||
"intersheets_ref_prefix": "",
|
|
||||||
"intersheets_ref_short": false,
|
|
||||||
"intersheets_ref_show": false,
|
|
||||||
"intersheets_ref_suffix": "",
|
|
||||||
"junction_size_choice": 3,
|
|
||||||
"label_size_ratio": 0.375,
|
|
||||||
"operating_point_overlay_i_precision": 3,
|
|
||||||
"operating_point_overlay_i_range": "~A",
|
|
||||||
"operating_point_overlay_v_precision": 3,
|
|
||||||
"operating_point_overlay_v_range": "~V",
|
|
||||||
"overbar_offset_ratio": 1.23,
|
|
||||||
"pin_symbol_size": 25.0,
|
|
||||||
"text_offset_ratio": 0.15
|
|
||||||
},
|
|
||||||
"legacy_lib_dir": "",
|
|
||||||
"legacy_lib_list": [],
|
|
||||||
"meta": {
|
|
||||||
"version": 1
|
|
||||||
},
|
|
||||||
"net_format_name": "",
|
|
||||||
"page_layout_descr_file": "",
|
|
||||||
"plot_directory": "",
|
|
||||||
"reuse_designators": true,
|
|
||||||
"space_save_all_events": true,
|
|
||||||
"spice_current_sheet_as_root": false,
|
|
||||||
"spice_external_command": "spice \"%I\"",
|
|
||||||
"spice_model_current_sheet_as_root": true,
|
|
||||||
"spice_save_all_currents": false,
|
|
||||||
"spice_save_all_dissipations": false,
|
|
||||||
"spice_save_all_voltages": false,
|
|
||||||
"subpart_first_id": 65,
|
|
||||||
"subpart_id_separator": 0,
|
|
||||||
"top_level_sheets": [
|
|
||||||
{
|
|
||||||
"filename": "water_temp.kicad_sch",
|
|
||||||
"name": "water_temp",
|
|
||||||
"uuid": "c1e691f1-9ee7-4a71-abd3-04b9ff725907"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"used_designators": "U5,C2",
|
|
||||||
"variants": []
|
|
||||||
},
|
|
||||||
"sheets": [
|
|
||||||
[
|
|
||||||
"c1e691f1-9ee7-4a71-abd3-04b9ff725907",
|
|
||||||
"water_temp"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"text_variables": {},
|
|
||||||
"tuning_profiles": {
|
|
||||||
"meta": {
|
|
||||||
"version": 0
|
|
||||||
},
|
|
||||||
"tuning_profiles_impedance_geometric": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
|
@ -13,12 +13,6 @@ platform = espressif32
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
build_flags =
|
|
||||||
-D DEBUG
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
zinggjm/GxEPD2@^1.5.6
|
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.5.0
|
||||||
bblanchon/ArduinoJson@^7.0.4
|
|
||||||
peterus/esp-logger@^1.0.0
|
|
||||||
sandeepmistry/LoRa@^0.8.0
|
sandeepmistry/LoRa@^0.8.0
|
||||||
olikraus/U8g2_for_Adafruit_GFX@^1.8.0
|
|
||||||
milesburton/DallasTemperature@^3.11.0
|
|
||||||
|
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <SPIFFS.h>
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
|
|
||||||
Config::Config()
|
|
||||||
{
|
|
||||||
_filePath = "/config.json";
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Init config");
|
|
||||||
if (!SPIFFS.begin(false))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "SPIFFS Mount Failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
readFile(SPIFFS, _filePath.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::readFile(fs::FS &fs, const char *fileName)
|
|
||||||
{
|
|
||||||
JsonDocument data;
|
|
||||||
File configFile = fs.open(fileName, "r");
|
|
||||||
DeserializationError error = deserializeJson(data, configFile);
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to read file, using default configuration");
|
|
||||||
}
|
|
||||||
|
|
||||||
LoraConfig lora;
|
|
||||||
lora.frequency = data["lora"]["frequency"].as<long>();
|
|
||||||
lora.spreadingFactor = data["lora"]["spreadingFactor"].as<int>();
|
|
||||||
lora.signalBandwidth = data["lora"]["signalBandwidth"].as<long>();
|
|
||||||
lora.codingRate4 = data["lora"]["codingRate4"].as<int>();
|
|
||||||
lora.power = data["lora"]["power"].as<int>();
|
|
||||||
logConfigInfo(data);
|
|
||||||
configFile.close();
|
|
||||||
|
|
||||||
loraConfig = lora;
|
|
||||||
|
|
||||||
isConfigLoaded = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::writeData()
|
|
||||||
{
|
|
||||||
JsonDocument doc;
|
|
||||||
|
|
||||||
JsonObject lora = doc["lora"].to<JsonObject>();
|
|
||||||
lora["frequency"] = 433775000;
|
|
||||||
lora["spreadingFactor"] = 12;
|
|
||||||
lora["signalBandwidth"] = 125000;
|
|
||||||
lora["codingRate4"] = 5;
|
|
||||||
lora["power"] = 20;
|
|
||||||
|
|
||||||
// Delete existing file, otherwise the configuration is appended to the file
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Write DATA to file");
|
|
||||||
|
|
||||||
SPIFFS.remove(_filePath);
|
|
||||||
File configFile = SPIFFS.open(_filePath.c_str(), "w");
|
|
||||||
if (!configFile)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to open file for writing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize the JSON document to the file
|
|
||||||
if (serializeJson(doc, configFile) == 0)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to write to file");
|
|
||||||
}
|
|
||||||
|
|
||||||
logConfigInfo(doc);
|
|
||||||
// Close the file
|
|
||||||
configFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::logConfigInfo(JsonDocument& doc) {
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Logging configuration data:");
|
|
||||||
|
|
||||||
JsonObject rootJson = doc.as<JsonObject>();
|
|
||||||
|
|
||||||
// Iterate over each key-value pair at the root level
|
|
||||||
for (auto kvp : rootJson) {
|
|
||||||
String key = kvp.key().c_str();
|
|
||||||
String value;
|
|
||||||
|
|
||||||
// Get the value associated with the key
|
|
||||||
const JsonVariant& jsonValue = kvp.value();
|
|
||||||
|
|
||||||
// Check the type of the JSON value and convert it to a string accordingly
|
|
||||||
if (jsonValue.is<String>()) {
|
|
||||||
value = jsonValue.as<String>();
|
|
||||||
} else if (jsonValue.is<int>()) {
|
|
||||||
value = String(jsonValue.as<int>());
|
|
||||||
} else if (jsonValue.is<long>()) {
|
|
||||||
value = String(jsonValue.as<long>());
|
|
||||||
} else if (jsonValue.is<bool>()) {
|
|
||||||
value = jsonValue.as<bool>() ? "true" : "false";
|
|
||||||
} else if (jsonValue.is<JsonArray>() || jsonValue.is<JsonObject>()) {
|
|
||||||
JsonDocument tempJson;
|
|
||||||
tempJson.set(jsonValue);
|
|
||||||
serializeJson(tempJson, value);
|
|
||||||
} else if (jsonValue.isNull()) {
|
|
||||||
value = "null";
|
|
||||||
} else {
|
|
||||||
value = "Unsupported data type";
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", (key + ": " + value).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef CONFIG_H
|
|
||||||
#define CONFIG_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <FS.h>
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
|
|
||||||
class LoraConfig {
|
|
||||||
public:
|
|
||||||
long frequency;
|
|
||||||
int spreadingFactor;
|
|
||||||
long signalBandwidth;
|
|
||||||
int codingRate4;
|
|
||||||
int power;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Config {
|
|
||||||
public:
|
|
||||||
bool isConfigLoaded = false;
|
|
||||||
LoraConfig loraConfig;
|
|
||||||
Config();
|
|
||||||
void writeData();
|
|
||||||
|
|
||||||
void logConfigInfo(JsonDocument& configJson);
|
|
||||||
private:
|
|
||||||
void readFile(fs::FS &fs, const char *fileName);
|
|
||||||
String _filePath;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
#include <Fonts/FreeMonoBold9pt7b.h>
|
|
||||||
#include <Fonts/FreeSerifBold24pt7b.h>
|
|
||||||
#include "eink.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
|
|
||||||
Eink::Eink(int csPin, int dcPin, int rstPin, int busyPin)
|
|
||||||
: eink(GxEPD2_213_BN(csPin, dcPin, rstPin, busyPin)), u8g2Fonts()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::setup_eink()
|
|
||||||
{
|
|
||||||
|
|
||||||
SPI.begin(EPD_SCLK, EPD_MISO, EPD_MOSI);
|
|
||||||
eink.init(115200, true, 2, false);
|
|
||||||
eink.setRotation(1);
|
|
||||||
eink.fillScreen(GxEPD_WHITE);
|
|
||||||
eink.setTextColor(GxEPD_BLACK);
|
|
||||||
eink.setFullWindow();
|
|
||||||
u8g2Fonts.begin(eink);
|
|
||||||
u8g2Fonts.setFont(u8g2_font_7x13_tf);
|
|
||||||
u8g2Fonts.setForegroundColor(GxEPD_BLACK); // apply Adafruit GFX color
|
|
||||||
u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "Display init done!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::show_display(String header, int wait)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "One line: %s", header.c_str());
|
|
||||||
eink.setFont(&FreeMonoBold9pt7b);
|
|
||||||
eink.setCursor(0, 10);
|
|
||||||
eink.println(header);
|
|
||||||
eink.println("Line 2");
|
|
||||||
eink.println("Line 3");
|
|
||||||
eink.println("Line 4");
|
|
||||||
eink.display();
|
|
||||||
delay(wait);
|
|
||||||
|
|
||||||
int16_t x1, y1;
|
|
||||||
uint16_t w, h;
|
|
||||||
eink.getTextBounds(header, 0, 0, &x1, &y1, &w, &h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::show_temp(float temperature)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "Show temp: %f", temperature);
|
|
||||||
|
|
||||||
int textX = 50;
|
|
||||||
//u8g2Fonts.setFont(u8g2_font_fur42_tf);
|
|
||||||
u8g2Fonts.setFont(u8g2_font_inb46_mf);
|
|
||||||
|
|
||||||
drawString(textX, 70, String(temperature, 1) + "°", LEFT);
|
|
||||||
drawMercury(temperature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::show_internal_temp(int x, int y, float temperature)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "Show internal temp: %f", temperature);
|
|
||||||
u8g2Fonts.setFont(u8g2_font_7x13_tf);
|
|
||||||
drawString(x + 60, y - 11, String(temperature, 1) + "°", LEFT);
|
|
||||||
}
|
|
||||||
void Eink::show_count(int x, int y, float cnt, String unit)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "Show cnt: %f", cnt);
|
|
||||||
u8g2Fonts.setFont(u8g2_font_7x13_tf);
|
|
||||||
drawString(x + 60, y - 11, unit + String(cnt, 1), LEFT);
|
|
||||||
}
|
|
||||||
void Eink::drawSignalBars(int x, int y, int percentage)
|
|
||||||
{
|
|
||||||
// Define stapler properties
|
|
||||||
const int staplerWidth = 4;
|
|
||||||
const int staplerHeight = 14;
|
|
||||||
const int staplerSpacing = 2;
|
|
||||||
int numBars = percentage / 20;
|
|
||||||
|
|
||||||
// Limit numBars to the maximum (5 staplers)
|
|
||||||
numBars = min(numBars, 5); // Ensure no more than 5 staplers are drawn
|
|
||||||
int staplerX;
|
|
||||||
int currentHeight;
|
|
||||||
int staplerY;
|
|
||||||
// Loop to draw staplers with variable heights and bottom alignment
|
|
||||||
for (int i = 0; i < numBars; i++)
|
|
||||||
{
|
|
||||||
// Calculate x-position for each stapler
|
|
||||||
staplerX = x + i * (staplerWidth + staplerSpacing);
|
|
||||||
|
|
||||||
// Calculate stapler height based on the number of bars (1 to 5)
|
|
||||||
currentHeight = staplerHeight * (i + 1) / 6; // Scales from 1/5 to full height
|
|
||||||
|
|
||||||
// Calculate y-position for bottom alignment
|
|
||||||
staplerY = y - currentHeight; // Subtract height for bottom placement
|
|
||||||
// Draw the stapler body (rectangle)
|
|
||||||
eink.fillRect(staplerX, staplerY, staplerWidth, currentHeight, GxEPD_BLACK);
|
|
||||||
}
|
|
||||||
|
|
||||||
drawString(staplerX + staplerWidth + 2, staplerY, String(percentage) + "%", LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::display(bool partialupgrade)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "Update display");
|
|
||||||
|
|
||||||
eink.display(partialupgrade);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::drawMercury(float temperature)
|
|
||||||
{
|
|
||||||
int x = 20;
|
|
||||||
int y = 30;
|
|
||||||
int height = 60;
|
|
||||||
int width = 10;
|
|
||||||
int mercuryLevel = map(temperature, 5.0, 35.0, 10, height);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "mercuryLevel: %d", mercuryLevel);
|
|
||||||
|
|
||||||
int radius = 14;
|
|
||||||
eink.drawRect(x, y - radius + 2, width, height, GxEPD_BLACK);
|
|
||||||
|
|
||||||
eink.drawCircle(x + (width / 2), y + height, radius, GxEPD_BLACK);
|
|
||||||
eink.fillCircle(x + (width / 2), y + height, radius - 2, GxEPD_BLACK);
|
|
||||||
|
|
||||||
eink.fillRect(
|
|
||||||
x + 2,
|
|
||||||
y + height - mercuryLevel - radius + 2,
|
|
||||||
width - 4,
|
|
||||||
mercuryLevel,
|
|
||||||
GxEPD_BLACK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::drawBattery(int x, int y, int percentage)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "EINK", "drawBattery: %d %", percentage);
|
|
||||||
eink.drawRect(x + 15, y - 12, 19, 10, GxEPD_BLACK);
|
|
||||||
eink.fillRect(x + 34, y - 10, 2, 5, GxEPD_BLACK);
|
|
||||||
eink.fillRect(x + 17, y - 10, 15 * percentage / 100.0, 6, GxEPD_BLACK);
|
|
||||||
drawString(x + 60, y - 11, String(percentage) + "%", RIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Eink::drawString(int x, int y, String text, alignmentType alignment)
|
|
||||||
{
|
|
||||||
int16_t x1, y1; // the bounds of x,y and w and h of the variable 'text' in pixels.
|
|
||||||
uint16_t w, h;
|
|
||||||
eink.setTextWrap(false);
|
|
||||||
eink.getTextBounds(text, x, y, &x1, &y1, &w, &h);
|
|
||||||
if (alignment == RIGHT)
|
|
||||||
x = x - w;
|
|
||||||
if (alignment == CENTER)
|
|
||||||
x = x - w / 2;
|
|
||||||
u8g2Fonts.setCursor(x + 2, y + h);
|
|
||||||
u8g2Fonts.print(text);
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef EINK_H
|
|
||||||
#define EINK_H
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <GxEPD2_BW.h>
|
|
||||||
#include "epd/GxEPD2_213.h"
|
|
||||||
#include <U8g2_for_Adafruit_GFX.h>
|
|
||||||
#include "pins.hpp"
|
|
||||||
|
|
||||||
class Eink {
|
|
||||||
public:
|
|
||||||
Eink(int csPin = EPD_CS, int dcPin = EPD_DC, int rstPin = EPD_RSET, int busyPin = EPD_BUSY);
|
|
||||||
void setup_eink();
|
|
||||||
void show_temp(float temperature);
|
|
||||||
void show_internal_temp(int x, int y, float temperature);
|
|
||||||
void show_count(int x, int y, float cnt, String unit);
|
|
||||||
void show_display(String header, int wait=100);
|
|
||||||
void drawBattery(int x, int y, int percentage=100);
|
|
||||||
void drawSignalBars(int x, int y, int numBars);
|
|
||||||
void display(bool partialupgrade = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;
|
|
||||||
enum alignmentType {LEFT, RIGHT, CENTER};
|
|
||||||
void drawMercury(float temperature);
|
|
||||||
void drawString(int x, int y, String text, alignmentType alignment);
|
|
||||||
void drawCircleSegment(int x0, int y0, int radius, int startAngle, int endAngle);
|
|
||||||
GxEPD2_BW<GxEPD2_213_BN, GxEPD2_213_BN::HEIGHT> eink;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* EINK_H */
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
|
|
||||||
#include "io.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "pins.hpp"
|
|
||||||
#include "WiFi.h"
|
|
||||||
#include "driver/adc.h"
|
|
||||||
#include <esp_wifi.h>
|
|
||||||
#include <esp_bt.h>
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
|
|
||||||
|
|
||||||
IO::IO() : oneWire(DI_DALLAS), sensors(&oneWire) {
|
|
||||||
// Constructor body (if needed)
|
|
||||||
}
|
|
||||||
|
|
||||||
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
|
|
||||||
#define TIME_TO_SLEEP 600
|
|
||||||
|
|
||||||
void IO::setup_io()
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "SETUP IO");
|
|
||||||
oneWire.begin(DI_DALLAS);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "oneWire.begin");
|
|
||||||
sensors.begin();
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "sensors.begi");
|
|
||||||
sensors.setResolution(12);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IO::set_low_power()
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "Set lower power attrs");
|
|
||||||
|
|
||||||
pinMode(DI_LED, OUTPUT);
|
|
||||||
digitalWrite(DI_LED, LOW); // TODO check if pin 22(ledbuiltin 2) is a led
|
|
||||||
setCpuFrequencyMhz(80);
|
|
||||||
WiFi.mode(WIFI_OFF);
|
|
||||||
btStop();
|
|
||||||
esp_wifi_stop();
|
|
||||||
esp_bt_controller_disable();
|
|
||||||
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
|
|
||||||
adc_power_on();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IO::set_deep_sleep()
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "Going to sleep");
|
|
||||||
esp_deep_sleep_start();
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "Will not reach");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t IO::read_battery()
|
|
||||||
{
|
|
||||||
uint8_t percentage = 100;
|
|
||||||
|
|
||||||
float voltage = analogRead(ADC_BATTERY) / 4096.0 * 7.46;
|
|
||||||
// float voltage = analogRead(35) / 4096.0 * 7.46;
|
|
||||||
if (voltage > 1)
|
|
||||||
{ // Only display if there is a valid reading
|
|
||||||
percentage = 2836.9625 * pow(voltage, 4) - 43987.4889 * pow(voltage, 3) + 255233.8134 * pow(voltage, 2) - 656689.7123 * voltage + 632041.7303;
|
|
||||||
if (voltage >= 4.20)
|
|
||||||
percentage = 100;
|
|
||||||
if (voltage <= 3.50)
|
|
||||||
percentage = 0;
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Voltage: %f", voltage);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Percentage: %d", percentage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return percentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
float IO::read_temp()
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "read_temp");
|
|
||||||
sensors.requestTemperatures(); // Request temperature readings
|
|
||||||
delay(1000);
|
|
||||||
float tempC = sensors.getTempCByIndex(0);
|
|
||||||
if (tempC != DEVICE_DISCONNECTED_C)
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Temp: %f", tempC);
|
|
||||||
}
|
|
||||||
else if(tempC == -127.00) {
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Couldn't read temp");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Couldn't read temp");
|
|
||||||
}
|
|
||||||
return tempC;
|
|
||||||
}
|
|
||||||
|
|
||||||
float IO::read_internal_temp()
|
|
||||||
{
|
|
||||||
float chipTemp = temperatureRead();
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "chipTemp: %f", chipTemp);
|
|
||||||
return chipTemp;
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#ifndef IO_H
|
|
||||||
#define IO_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <OneWire.h>
|
|
||||||
#include <DallasTemperature.h>
|
|
||||||
|
|
||||||
|
|
||||||
class IO {
|
|
||||||
public:
|
|
||||||
IO();
|
|
||||||
void setup_io();
|
|
||||||
void set_low_power();
|
|
||||||
void set_deep_sleep();
|
|
||||||
float read_temp();
|
|
||||||
float read_internal_temp();
|
|
||||||
uint8_t read_battery();
|
|
||||||
private:
|
|
||||||
OneWire oneWire;
|
|
||||||
DallasTemperature sensors;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* IO_H */
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#include "config.hpp"
|
|
||||||
#include "lorahandler.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "pins.hpp"
|
|
||||||
|
|
||||||
extern logging::Logger logger;
|
|
||||||
extern Config config;
|
|
||||||
|
|
||||||
void LoraHandler::setup()
|
|
||||||
{
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "Set SPI pins!");
|
|
||||||
SPI.begin(RADIO_SCK, RADIO_MISO, RADIO_MOSI, RADIO_CS);
|
|
||||||
LoRa.setPins(RADIO_CS, RADIO_RST, RADIO_IRQ);
|
|
||||||
|
|
||||||
long freq = config.loraConfig.frequency;
|
|
||||||
if (!LoRa.begin(freq))
|
|
||||||
{
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "Starting LoRa failed!");
|
|
||||||
// show_display("ERROR", "Starting LoRa failed!");
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoRa.setSpreadingFactor(config.loraConfig.spreadingFactor);
|
|
||||||
LoRa.setSignalBandwidth(config.loraConfig.signalBandwidth);
|
|
||||||
LoRa.setCodingRate4(config.loraConfig.codingRate4);
|
|
||||||
LoRa.enableCrc();
|
|
||||||
LoRa.setTxPower(config.loraConfig.power);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "LoRa init done!");
|
|
||||||
String currentLoRainfo = "LoRa Freq: " + String(config.loraConfig.frequency) + " / SF:" + String(config.loraConfig.spreadingFactor) + " / CR: " + String(config.loraConfig.codingRate4);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", currentLoRainfo.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceivedLoRaPacket LoraHandler::receivePacket()
|
|
||||||
{
|
|
||||||
ReceivedLoRaPacket receivedLoraPacket;
|
|
||||||
String packet = "";
|
|
||||||
int packetSize = LoRa.parsePacket();
|
|
||||||
if (packetSize)
|
|
||||||
{
|
|
||||||
while (LoRa.available())
|
|
||||||
{
|
|
||||||
int inChar = LoRa.read();
|
|
||||||
packet += (char)inChar;
|
|
||||||
}
|
|
||||||
receivedLoraPacket.text = packet;
|
|
||||||
receivedLoraPacket.rssi = LoRa.packetRssi();
|
|
||||||
receivedLoraPacket.snr = LoRa.packetSnr();
|
|
||||||
receivedLoraPacket.freqError = LoRa.packetFrequencyError();
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Rx", "---> %s", packet.c_str());
|
|
||||||
}
|
|
||||||
return receivedLoraPacket;
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#ifndef LORAHANDLER_H
|
|
||||||
#define LORAHANDLER_H
|
|
||||||
|
|
||||||
#include "config.hpp"
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <LoRa.h>
|
|
||||||
|
|
||||||
struct ReceivedLoRaPacket {
|
|
||||||
String text;
|
|
||||||
int rssi;
|
|
||||||
float snr;
|
|
||||||
int freqError;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoraHandler {
|
|
||||||
public:
|
|
||||||
void setup();
|
|
||||||
ReceivedLoRaPacket receivePacket();
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LORAHANDLER_H */
|
|
||||||
|
|
@ -1,66 +1,112 @@
|
||||||
#include <logger.h>
|
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||||
#include "config.hpp"
|
#include <WiFi.h>
|
||||||
#include "eink.hpp"
|
#include <SPI.h>
|
||||||
#include "io.hpp"
|
#include <LoRa.h>
|
||||||
|
// #include "SSD1306.h"
|
||||||
logging::Logger logger;
|
#include<Arduino.h>
|
||||||
Eink eink;
|
|
||||||
IO io;
|
|
||||||
|
|
||||||
RTC_DATA_ATTR int bootCount = 0;
|
|
||||||
RTC_DATA_ATTR int updateCount = 0;
|
|
||||||
RTC_DATA_ATTR float last_temp = 20;
|
|
||||||
RTC_DATA_ATTR int last_battery = 0;
|
|
||||||
bool update = false;
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
//OLED pins to ESP32 GPIOs via this connecthin:
|
||||||
{
|
//OLED_SDA GPIO4
|
||||||
|
//OLED_SCL GPIO15
|
||||||
|
//OLED_RST GPIO16
|
||||||
|
|
||||||
|
SSD1306 display(0x3c, 4, 15);
|
||||||
|
|
||||||
|
// WIFI_LoRa_32 ports
|
||||||
|
// GPIO5 SX1278 SCK
|
||||||
|
// GPIO19 SX1278 MISO
|
||||||
|
// GPIO27 SX1278 MOSI
|
||||||
|
// GPIO18 SX1278 CS
|
||||||
|
// GPIO14 SX1278 RESET
|
||||||
|
// GPIO26 SX1278 IRQ(Interrupt Request)
|
||||||
|
|
||||||
|
#define SS 18
|
||||||
|
#define RST 14
|
||||||
|
#define DI0 26
|
||||||
|
// #define BAND 429E6 //915E6
|
||||||
|
|
||||||
|
// #define BAND 434500000.00
|
||||||
|
#define BAND 434500000.00
|
||||||
|
|
||||||
|
#define spreadingFactor 9
|
||||||
|
// #define SignalBandwidth 62.5E3
|
||||||
|
#define SignalBandwidth 31.25E3
|
||||||
|
#define preambleLength 8
|
||||||
|
#define codingRateDenominator 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(25,OUTPUT); //Send success, LED will bright 1 second
|
||||||
|
|
||||||
|
pinMode(16,OUTPUT);
|
||||||
|
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
|
||||||
|
delay(50);
|
||||||
|
digitalWrite(16, HIGH);
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "Boot number: %i", bootCount);
|
while (!Serial); //If just the the basic function, must connect to a computer
|
||||||
update = false;
|
|
||||||
#ifndef DEBUG
|
|
||||||
logger.setDebugLevel(logging::LoggerLevel::LOGGER_LEVEL_INFO);
|
|
||||||
#endif
|
|
||||||
io.setup_io();
|
|
||||||
io.set_low_power();
|
|
||||||
|
|
||||||
uint8_t battery = io.read_battery();
|
|
||||||
if (abs(battery - last_battery) >= 2)
|
|
||||||
{
|
|
||||||
last_battery = battery;
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "Battery: %i", battery);
|
|
||||||
|
|
||||||
float temp = io.read_temp();
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "TEMP: %f", temp);
|
|
||||||
if (abs(temp - last_temp) >= 0.5 && temp > -120)
|
|
||||||
{
|
|
||||||
last_temp = temp;
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
float internal_temp = io.read_internal_temp();
|
// Initialising the UI will init the display too.
|
||||||
eink.setup_eink();
|
display.init();
|
||||||
|
display.flipScreenVertically();
|
||||||
++bootCount;
|
display.setFont(ArialMT_Plain_10);
|
||||||
if (update)
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
{
|
display.drawString(5,5,"LoRa Sender");
|
||||||
++updateCount;
|
display.display();
|
||||||
eink.drawBattery(186, 14, battery); // eink width 250 - drawbattery width
|
|
||||||
eink.drawSignalBars(180 - 24 - 4, 12, 84); // drawbattery width - drawsignal
|
SPI.begin(5,19,27,18);
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "TEMP: %f", temp);
|
LoRa.setPins(SS,RST,DI0);
|
||||||
eink.show_temp(temp);
|
Serial.println("LoRa Sender");
|
||||||
eink.show_internal_temp(180 - 24 - 4 - 100, 12, internal_temp);
|
if (!LoRa.begin(BAND)) {
|
||||||
eink.show_count(180 - 24 - 4 - 100 - 60, 12, (float)bootCount, "c: ");
|
Serial.println("Starting LoRa failed!");
|
||||||
eink.show_count(180 - 24 - 4 - 100 - 60 - 50, 12, (float)bootCount, "u: ");
|
while (1);
|
||||||
eink.display(true);
|
|
||||||
}
|
}
|
||||||
io.set_deep_sleep();
|
|
||||||
|
Serial.print("LoRa Spreading Factor: ");
|
||||||
|
Serial.println(spreadingFactor);
|
||||||
|
LoRa.setSpreadingFactor(spreadingFactor);
|
||||||
|
|
||||||
|
Serial.print("LoRa Signal Bandwidth: ");
|
||||||
|
Serial.println(SignalBandwidth);
|
||||||
|
LoRa.setSignalBandwidth(SignalBandwidth);
|
||||||
|
|
||||||
|
LoRa.setCodingRate4(codingRateDenominator);
|
||||||
|
|
||||||
|
LoRa.setPreambleLength(preambleLength);
|
||||||
|
|
||||||
|
Serial.println("LoRa Initial OK!");
|
||||||
|
display.drawString(5,20,"LoRa Initializing OK!");
|
||||||
|
display.display();
|
||||||
|
delay(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop() {
|
||||||
{
|
Serial.print("Sending packet: ");
|
||||||
|
Serial.println(counter);
|
||||||
|
|
||||||
|
display.clear();
|
||||||
|
display.setFont(ArialMT_Plain_16);
|
||||||
|
display.drawString(3, 5, "Sending packet ");
|
||||||
|
display.drawString(50, 30, String(counter));
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
// send packet
|
||||||
|
LoRa.beginPacket();
|
||||||
|
LoRa.print("Hello..");
|
||||||
|
LoRa.print(counter);
|
||||||
|
LoRa.endPacket();
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
digitalWrite(25, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||||
|
delay(1000); // wait for a second
|
||||||
|
digitalWrite(25, LOW); // turn the LED off by making the voltage LOW
|
||||||
|
delay(1000); // wait for a second
|
||||||
|
|
||||||
|
// delay(3000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef PINS_H
|
|
||||||
#define PINS_H
|
|
||||||
|
|
||||||
// Pin assignments for EPD display
|
|
||||||
const int EPD_MOSI = 23;
|
|
||||||
const int EPD_MISO = -1; // elink no use
|
|
||||||
const int EPD_SCLK = 18;
|
|
||||||
|
|
||||||
const int EPD_BUSY = 4;
|
|
||||||
const int EPD_RSET = 16;
|
|
||||||
const int EPD_DC = 17;
|
|
||||||
const int EPD_CS = 5;
|
|
||||||
|
|
||||||
// Pin assignments for LORA module
|
|
||||||
const int RADIO_SCK = 5;
|
|
||||||
const int RADIO_MISO = 19;
|
|
||||||
const int RADIO_MOSI = 27;
|
|
||||||
const int RADIO_CS = 18; // CS --> NSS
|
|
||||||
const int RADIO_RST = 14;
|
|
||||||
const int RADIO_IRQ = 26; // IRQ --> DIO0
|
|
||||||
|
|
||||||
// Battery pin
|
|
||||||
const int ADC_BATTERY = 35; //builtin = 35
|
|
||||||
|
|
||||||
const int DI_DALLAS = 32;
|
|
||||||
// Builtin LED
|
|
||||||
const int DI_LED = LED_BUILTIN;
|
|
||||||
#endif /* PINS_H */
|
|
||||||
Loading…
Reference in New Issue