ESP32 node monitor

Step 7 Why did LND-pussy not connect?
The reason is (I think) that the certificate is self signed (as your browser also was complaining about).
At this moment I do not know (yet) how to create a really safe connection. Therefore I added the Client.SetInsecure() after each WiFiClientSecure client statement. Be aware that the local WiFi connection can be overheard, so don’t send any high priveliged macaroons that allow making transactions. Still not sure though, how insecure this is….

Step 8 Upload the modified program
xxd -p -c2000 ./lnd/data/chain/bitcoin/mainnet/readonly.macaroonThis will return your read only macaroon, that needs to be filled in in the wifi portal (or hard code it into the software code, as shown ). Connect with your phone’s WiFi to:
//////////////LOAD LIBRARIES////////////////
#include “FS.h”
#include
#include
#include
#include “SPIFFS.h”
/////////////////SOME VARIABLES///////////////////
int new_balance = 0;
int balance = 0;
int new_confirmed_balance = 0;
int confirmed_balance = 0;
bool synced_to_chain = false;
bool first_check = true;
bool first_check1 = true;
const char* lnd_check;
char lnd_server[40]=”10.0.10.50″;
char lnd_port[6] = “8080”;
char lnd_macaroon[500] = “0201036c6e6402ac01030a107_etc”;
char static_ip[16] = “10.0.0.120”;
char static_gw[16] = “10.0.0.1”;
char static_sn[16] = “255.255.255.0”;
bool shouldSaveConfig = true;
const char* spiffcontent = “”;
String spiffing;
/////////////////////SETUP////////////////////////
void setup() {
Serial.begin(115200);
// CATHODE RGB SETUP, 18 WILL BE PWM FOR DIMMING THE LED
pinMode(16, OUTPUT);
pinMode(17, OUTPUT);
pinMode(5, OUTPUT);
// the number of the LED pin
const int ledPin = 18; // 18 corresponds to GPIO18
// configure LED PWM functionalitites
ledcSetup(0, 5000, 8); //ledchannel 0, frequency 5000 and resolution 8
// attach the channel to the GPIO to be controlled
ledcAttachPin(18, 0); // connect pin 18 with led channel 0
ledcWrite(0, 255-80); //channel 0 to low led brightness (0-255)
pink();
// START PORTAL
NodeUitGans();
blue();
}
///////////////////MAIN LOOP//////////////////////
void loop() {
getinfo();
delay(3000);
getonchainbalance();
delay(3000);
getlnbalance();
delay(3000);
}
//////////////////LED SEQUENCES///////////////////
//GREEN — running
void green(){
digitalWrite(16, HIGH); digitalWrite(17, HIGH); digitalWrite(5, LOW);
}
//RED — down
void red(){
digitalWrite(16, HIGH); digitalWrite(17, LOW); digitalWrite(5, HIGH);
}
// PINK — synching
void pink(){
digitalWrite(16, LOW); digitalWrite(17, LOW); digitalWrite(5, HIGH);
}
// PINK — synching
void blue(){
digitalWrite(16, LOW); digitalWrite(17, HIGH); digitalWrite(5, HIGH);
}
//DISCO LOOP // transaction
void disco(){
for (int i = 0; i <= 10; i++) {
ledcWrite(0, 0); //channel 0 to max led brightness (0-255)
digitalWrite(16, LOW); digitalWrite(17, HIGH); digitalWrite(5, HIGH);
delay(100);
digitalWrite(16, HIGH); digitalWrite(17, HIGH); digitalWrite(5, LOW);
delay(100);
digitalWrite(16, HIGH); digitalWrite(17, LOW); digitalWrite(5, HIGH);
delay(100);
digitalWrite(16, LOW); digitalWrite(17, LOW); digitalWrite(5, HIGH);
delay(100);
digitalWrite(16, LOW); digitalWrite(17, HIGH); digitalWrite(5, LOW);
delay(100);
digitalWrite(16, HIGH); digitalWrite(17, LOW); digitalWrite(5, LOW);
delay(100);
ledcWrite(0, 255-80); //channel 0 to low led brightness (0-255)
}
green();
}
//////////////////NODE CALLS///////////////////
void getinfo() {
WiFiClientSecure client;
client.setInsecure();
const char* lndserver = lnd_server;
const char* macaroon = lnd_macaroon;
int lndport = atoi( lnd_port );
// Serial.println(lndserver);
// Serial.println(lndport);
if (!client.connect(lndserver, lndport)){
red();
Serial.println(“Not connected to client”);
return;
}
client.println(String(“GET “)+ “https://” + lndserver +”:”+ lndport + “/v1/getinfo HTTP/1.1\r\n” +
“Host: ” + lndserver +”:”+ lndport +”\r\n” +
“User-Agent: ESP322\r\n” +
“Grpc-Metadata-macaroon:” + macaroon + “\r\n” +
“Content-Type: application/json\r\n” +
“Connection: close\r\n” +
“\n”);
String line = client.readStringUntil(‘\n’);
while (client.connected()) {
String line = client.readStringUntil(‘\n’);
if (line == “\r”) {
break;
}
}
String content = client.readStringUntil(‘\n’);
client.stop();
const size_t capacity = JSON_OBJECT_SIZE(3) + 620;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, content);
lnd_check = doc[“alias”];
if (!lnd_check){
red();
delay(1000);
return;
}
Serial.println(“alias: ” + String(lnd_check));
synced_to_chain = doc[“synced_to_chain”];
if(synced_to_chain == true){
green();
Serial.println(“synced_to_chain: yes”);
}
else{
pink();
Serial.println(“synced_to_chain: no”);
}
}
void getonchainbalance() {
WiFiClientSecure client;
client.setInsecure();
const char* lndserver = lnd_server;
const char* macaroon = lnd_macaroon;
int lndport = atoi( lnd_port );
if (!client.connect(lndserver, lndport)){
red();
delay(1000);
return;
}
client.print(String(“GET “)+ “https://” + lndserver +”:”+ lndport + “/v1/balance/blockchain HTTP/1.1\r\n” +
“Host: ” + lndserver +”:”+ lndport +”\r\n” +
“User-Agent: ESP322\r\n” +
“Grpc-Metadata-macaroon:” + macaroon + “\r\n” +
“Content-Type: application/json\r\n” +
“Connection: close\r\n” +
“\n”);
String line = client.readStringUntil(‘\n’);
while (client.connected()) {
String line = client.readStringUntil(‘\n’);
if (line == “\r”) {
break;
}
}
String content = client.readStringUntil(‘\n’);
client.stop();
const size_t capacity = JSON_OBJECT_SIZE(3) + 620;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, content);
new_confirmed_balance = doc[“confirmed_balance”];
if(new_confirmed_balance > confirmed_balance){
if(first_check == false){
confirmed_balance = new_confirmed_balance;
Serial.println(new_confirmed_balance);
disco();
}
else{
confirmed_balance = new_confirmed_balance;
first_check = false;
}
}
Serial.println(“old_onchain_balance: ” + String(confirmed_balance));
Serial.println(“new_onchain_balance: ” + String(new_confirmed_balance));
}
void getlnbalance() {
WiFiClientSecure client;
client.setInsecure();
const char* lndserver = lnd_server;
const char* macaroon = lnd_macaroon;
int lndport = atoi( lnd_port );
if (!client.connect(lndserver, lndport)){
red();
return;
}
client.print(String(“GET “)+ “https://” + lndserver +”:”+ lndport + “/v1/balance/channels HTTP/1.1\r\n” +
“Host: ” + lndserver +”:”+ lndport +”\r\n” +
“User-Agent: ESP322\r\n” +
“Grpc-Metadata-macaroon:” + macaroon + “\r\n” +
“Content-Type: application/json\r\n” +
“Connection: close\r\n” +
“\n”);
String line = client.readStringUntil(‘\n’);
while (client.connected()) {
String line = client.readStringUntil(‘\n’);
if (line == “\r”) {
break;
}
}
String content = client.readStringUntil(‘\n’);
client.stop();
const size_t capacity = JSON_OBJECT_SIZE(3) + 620;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, content);
new_balance = doc[“balance”];
if(new_balance > balance){
if(first_check1 == false){
balance = new_balance;
disco();
}
else{
balance = new_balance;
first_check1 = false;
}
}
Serial.println(“old_lnd_balance : ” + String(balance));
Serial.println(“new_lnd_balance : ” + String(new_balance));
}
void NodeUitGans(){
WiFiManager wm;
Serial.println(“mounting FS…”);
while(!SPIFFS.begin(true)){
Serial.println(“failed to mount FS”);
delay(200);
}
//CHECK IF RESET IS TRIGGERED/WIPE DATA
for (int i = 0; i <= 5; i++) {
if(touchRead(4) < 50){
File file = SPIFFS.open(“/config.txt”, FILE_WRITE);
file.print(“placeholder”);
wm.resetSettings();
}
delay(1000);
}
//MOUNT FS AND READ CONFIG.JSON
File file = SPIFFS.open(“/config.txt”);
spiffing = file.readStringUntil(‘\n’);
spiffcontent = spiffing.c_str();
DynamicJsonDocument json(1024);
deserializeJson(json, spiffcontent);
if(String(spiffcontent) != “placeholder”){
strcpy(lnd_server, json[“lnd_server”]);
strcpy(lnd_port, json[“lnd_port”]);
strcpy(lnd_macaroon, json[“lnd_macaroon”]);
}
//ADD PARAMS TO WIFIMANAGER
wm.setSaveConfigCallback(saveConfigCallback);
WiFiManagerParameter custom_lnd_server(“server”, “LND server”, lnd_server, 40);
WiFiManagerParameter custom_lnd_port(“port”, “LND port”, lnd_port, 6);
WiFiManagerParameter custom_lnd_macaroon(“macaroon”, “LND readonly macaroon”, lnd_macaroon, 500);
wm.addParameter(&custom_lnd_server);
wm.addParameter(&custom_lnd_port);
wm.addParameter(&custom_lnd_macaroon);
//IF RESET WAS TRIGGERED, RUN PORTAL AND WRITE FILES
if (!wm.autoConnect(“Nodeuitgans
“, “gakgakgak”)) {
Serial.println(“failed to connect and hit timeout”);
delay(3000);
ESP.restart();
delay(5000);
}
Serial.println(“connected :)”);
strcpy(lnd_server, custom_lnd_server.getValue());
strcpy(lnd_port, custom_lnd_port.getValue());
strcpy(lnd_macaroon, custom_lnd_macaroon.getValue());
if (shouldSaveConfig) {
Serial.println(“saving config”);
DynamicJsonDocument json(1024);
json[“lnd_server”] = lnd_server;
json[“lnd_port”] = lnd_port;
json[“lnd_macaroon”] = lnd_macaroon;
File configFile = SPIFFS.open(“/config.txt”, “w”);
if (!configFile) {
Serial.println(“failed to open config file for writing”);
}
serializeJsonPretty(json, Serial);
serializeJson(json, configFile);
configFile.close();
shouldSaveConfig = false;
}
Serial.println(“local ip”);
Serial.println(WiFi.localIP());
Serial.println(WiFi.gatewayIP());
Serial.println(WiFi.subnetMask());
}
void saveConfigCallback () {
Serial.println(“Should save config”);
shouldSaveConfig = true;
}
///////////OTHER COLOURS YOU COULD USE////////////
//AQUA digitalWrite(16, LOW); digitalWrite(17, HIGH); digitalWrite(5, LOW);
//LIME digitalWrite(16, HIGH); digitalWrite(17, LOW); digitalWrite(5, LOW);
Now we can stick the ESP32 and some LED’s on a bread board and start playing with the node monitor in the next step.