{"id":426,"date":"2021-10-19T19:44:48","date_gmt":"2021-10-19T19:44:48","guid":{"rendered":"https:\/\/www.lightninglouk.nl\/?page_id=426"},"modified":"2021-11-05T20:47:02","modified_gmt":"2021-11-05T20:47:02","slug":"esp32-node-monitor-page-5","status":"publish","type":"page","link":"https:\/\/www.lightninglouk.nl\/index.php\/esp32-node-monitor-page-1\/esp32-node-monitor-page-5\/","title":{"rendered":"ESP32 node monitor page 5"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"426\" class=\"elementor elementor-426\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-32a39fa5 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"32a39fa5\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-3946f812\" data-id=\"3946f812\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-794dfca1 elementor-widget elementor-widget-heading\" data-id=\"794dfca1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">ESP32 node monitor<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-5354fe23 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"5354fe23\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-25e0e4e2\" data-id=\"25e0e4e2\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5df493b3 elementor-widget elementor-widget-image\" data-id=\"5df493b3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1500\" height=\"337\" src=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Lightning-Louk-1500-kopie-e1630704244431.jpg\" class=\"attachment-full size-full wp-image-242\" alt=\"\" srcset=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Lightning-Louk-1500-kopie-e1630704244431.jpg 1500w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Lightning-Louk-1500-kopie-e1630704244431-300x67.jpg 300w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Lightning-Louk-1500-kopie-e1630704244431-1024x230.jpg 1024w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Lightning-Louk-1500-kopie-e1630704244431-768x173.jpg 768w\" sizes=\"(max-width: 1500px) 100vw, 1500px\" style=\"width:100%;height:22.47%;max-width:1500px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-46dc914f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"46dc914f\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1525f121\" data-id=\"1525f121\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-65d79a75 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"65d79a75\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-6b1a9b25\" data-id=\"6b1a9b25\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2747c076 elementor-align-left elementor-widget elementor-widget-button\" data-id=\"2747c076\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-xs\" href=\"https:\/\/www.lightninglouk.nl\/index.php\/esp32-node-monitor-page-4\/\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Previous page<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-49697892\" data-id=\"49697892\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3a80bc55 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3a80bc55\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-33071878\" data-id=\"33071878\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-2f07d9f2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"2f07d9f2\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-11602370\" data-id=\"11602370\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7bb42ac5 elementor-widget elementor-widget-heading\" data-id=\"7bb42ac5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Step 9 ESP32 on a breadboard<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6a5486ce elementor-widget elementor-widget-text-editor\" data-id=\"6a5486ce\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>On the right, you see the first attempt.<\/p>\n<p>I managed to get the first common cathode led burning green after checking my node.<\/p>\n<p>One the first led was fired-up, a second led was a piece of cake.<\/p>\n<p>Changing the colors of the leds is just a matter of software.<\/p>\n<p>Note 1: A led should get no more than 20 mA (I). With V=I*R, you can calculate that the resistance (R) should be 250 Ohm. I used 220 Ohm, which works nicely.<\/p>\n<p>Note 2: I connected a pulse width modulation output to the resistance connected to the common output. Later I discovered that this works perfectly if you only light-up one LED color at the time, but mixing colors did not work. Putting a PWM on every anode with each anode a resistor would probably solve the problem.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-7d3de620\" data-id=\"7d3de620\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0bb2d72 my-image-90 elementor-widget elementor-widget-image\" data-id=\"0bb2d72\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"750\" height=\"364\" src=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-1024x497.png\" class=\"attachment-large size-large wp-image-278\" alt=\"\" srcset=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-1024x497.png 1024w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-e1634988237897-300x146.png 300w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-768x373.png 768w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-1536x746.png 1536w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-2048x995.png 2048w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-1568x762.png 1568w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/09\/Breadboard-e1634988237897.png 600w\" sizes=\"(max-width: 750px) 100vw, 750px\" style=\"width:100%;height:48.5%;max-width:600px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-22a6ef8d elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"22a6ef8d\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-4276d603\" data-id=\"4276d603\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-146d21dd elementor-widget elementor-widget-heading\" data-id=\"146d21dd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Step 10 Sound hardware<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5e00a637 elementor-widget elementor-widget-text-editor\" data-id=\"5e00a637\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The most important feature of the Nodeuitgans is of course the geese honking sound.<\/p><p>Therefore I bought the PAM8302A 2.5W amplifier. The connections are simple:<\/p><ul><li>connect the audio in (A+) to\u00a0 one of the 2 DAC outputs of the ESP32. I used\u00a0 GPIO25 in this case.<\/li><li>connect the other audio input (A-) to the ground.<\/li><li>connect 2-5V input to the 5V pin of the ESP32.<br \/>Very important: connect a big capacitor (2200 uF) near the 5V connection, in order to limit the distortions caused by power dips during WiFi communication.<\/li><li>connect the ground to one of the ground pins of the ESP32.<\/li><li>connect the shutdown (SD) input to one of the free GPIO (outputs). I used GPIO0. This allows you to shutdown the amplifier when not in use, which reduces a lot of noise.<\/li><li>Use a 4-8 ohm speaker and connect it to the PAM8302A speaker outputs<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-6616dc1c\" data-id=\"6616dc1c\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-cc16c6f elementor-widget elementor-widget-image\" data-id=\"cc16c6f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"451\" height=\"333\" src=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/PAM8302A.png\" class=\"attachment-large size-large wp-image-450\" alt=\"\" srcset=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/PAM8302A.png 451w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/PAM8302A-300x222.png 300w\" sizes=\"(max-width: 451px) 100vw, 451px\" style=\"width:100%;height:73.84%;max-width:451px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a9f3bc8 elementor-widget elementor-widget-image\" data-id=\"a9f3bc8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"364\" src=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-1024x497.jpg\" class=\"attachment-large size-large wp-image-446\" alt=\"\" srcset=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-1024x497.jpg 1024w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-300x146.jpg 300w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-768x373.jpg 768w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-1536x746.jpg 1536w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-2048x995.jpg 2048w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-1568x762.jpg 1568w, https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/2021\/10\/ESP-breadboard-final-rotated-e1634676373884.jpg 800w\" sizes=\"(max-width: 750px) 100vw, 750px\" style=\"width:100%;height:48.63%;max-width:800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-756aa13 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"756aa13\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-8e5384e\" data-id=\"8e5384e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a2646e4 elementor-widget elementor-widget-heading\" data-id=\"a2646e4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Step 11 Sound software<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8662937 elementor-widget elementor-widget-text-editor\" data-id=\"8662937\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The software to play sound is called XT_DAC_AUDIO.h<\/p><p>How to install and use it, can be found on the webpage of <a href=\"https:\/\/www.xtronical.com\/the-dacaudio-library-download-and-installation\/\" target=\"_blank\" rel=\"noopener\">Xtronical<\/a>.<\/p><p>I used the open source program <a href=\"https:\/\/www.audacityteam.org\/\" target=\"_blank\" rel=\"noopener\">Audacity<\/a> to mix a sound track to mono, and to reduce the sample rate to 8kHz. Although, this reduces the quality drastically, it also reduces storage space drastically. I discovered that storage space is scarce in the ESP32.<\/p><p>You can not simply use the sound file in the ESP. You first have to convert it to an eight bit unsigned wav file, and convert this again with xxd -i to a readable format. I got the info by looking at <a href=\"https:\/\/www.youtube.com\/watch?v=SCAKQsGt9wI\" target=\"_blank\" rel=\"noopener\">this<\/a> video.<\/p><p>One important thing I discovered, is that the loop() function needs to be looping quickly (without major delays) in order to produce sound. Therefore, the software bypasses all node and price checks when playing sound.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-bd0e5f3\" data-id=\"bd0e5f3\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7b4ac664 scroll-box600 elementor-widget elementor-widget-text-editor\" data-id=\"7b4ac664\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>\/\/\/\/\/\/\/\/\/\/\/\/\/\/LOAD LIBRARIES\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<\/p><p>#include &#8220;FS.h&#8221;<br \/>#include &lt;WiFiManager.h&gt; <br \/>#include &lt;ArduinoJson.h&gt;<br \/>#include &lt;WiFiClientSecure.h&gt;<br \/>#include &#8220;SPIFFS.h&#8221;<br \/>#include &#8220;Geese_honking.h&#8221;<br \/>#include &#8220;XT_DAC_Audio.h&#8221;<\/p><p>XT_Wav_Class GeeseHonk(Geese_honking_wav); \/\/ create an object of type XT_Wav_Class that is used by <br \/>\/\/ the dac audio class (below), passing wav data as parameter.<br \/><br \/>XT_DAC_Audio_Class DacAudio(25,0); \/\/ Create the main player class object. <br \/>\/\/ Use GPIO 25, one of the 2 DAC pins and timer 0<\/p><p>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/SOME VARIABLES\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<\/p><p>bool initial_startup = true;<\/p><p>const int default_intensity = 30; \/\/ default intensity of LED&#8217;s<br \/>const int max_intensity = 255; \/\/ max intensity of LED&#8217;s<br \/><br \/>char lnd_server[40] = &#8220;10.0.20.50&#8221;;<br \/>char lnd_port[6] = &#8220;8080&#8221;;<br \/>char lnd_macaroon[500] = &#8220;0201036c6e6402ac0103&#8230;bla..bla..bla&#8230;bc3&#8221;;<br \/>char static_ip[16] = &#8220;10.0.40.120&#8221;;<br \/>char static_gw[16] = &#8220;10.0.40.1&#8221;;<br \/>char static_sn[16] = &#8220;255.255.255.0&#8221;;<\/p><p>char price_server[40] = &#8220;api.coingecko.com&#8221;; \/\/ server adress for BTC price<br \/>char price_port[6] = &#8220;443&#8221;;<br \/>char BTC_ATH[16] = &#8220;67277&#8221;; \/\/ last all time high value of bitcoin in USD<br \/>char BTC_fapgans[16] = &#8220;70000&#8221;; \/\/ Next Satosh Radio fapgans (every 5K all time high)<br \/>char Connect_to_node[2] = &#8220;Y&#8221;;<br \/>bool shouldSaveConfig = true;<br \/>String lnd_Alias = &#8220;&#8221;;<br \/>boolean lnd_Synced;<br \/>int block_Height;<br \/>int old_block_height = 0;<br \/>int onchain_balance;<br \/>int old_onchain_balance = 0;<br \/>int lnd_balance;<br \/>int old_lnd_balance = 0;<br \/>int highest_invoice_settle_index=0;<br \/>int last_invoice_settle_index=0;<br \/>int last_invoice = 0;<br \/>int highest_payment_settle_index=0;<br \/>String last_payment_status=&#8221;&#8221;;<br \/>int last_payment_index = 0;<br \/>int USD_price = 0;<br \/>int rnd;<br \/>int remaining_delay;<br \/>int btc_ATH = atoi(BTC_ATH);<br \/>int btc_fapgans = atoi(BTC_fapgans);<br \/>int Play_nr_Fapgans = 0;<br \/>int i_fap = 0;<br \/>bool has_been_significantly_lower =true;<br \/>int ATH_threshold = 250; \/\/threshold for all time high blinking<br \/>bool onchainIsHigher=false;<br \/>bool onchainIsLower=false;<br \/>bool lndIsHigher=false;<br \/>bool lndIsLower=false;<\/p><p>const char* spiffcontent = &#8220;&#8221;;<br \/>String spiffing;<\/p><p>struct LED {<br \/>int pins[4];<br \/>int channel;<br \/>} left_LED, right_LED;<br \/>int MuteSound = 0; \/\/ GPIO 0 is used for muting sound<br \/><br \/>\/\/ RGB colors<br \/>int RGB_green[3]= {LOW, HIGH, LOW }; \/\/ node running<br \/>int RGB_red[3] = {HIGH, LOW, LOW}; \/\/ node down<br \/>int RGB_pink[3] = {HIGH, LOW, HIGH}; \/\/ node syncing<br \/>int RGB_blue[3] = {LOW, LOW, HIGH}; \/\/ <br \/>int RGB_aqua[3] = {LOW, HIGH, HIGH };<br \/>int RGB_lime[3] = {HIGH, HIGH, LOW };<\/p><p>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/SETUP\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<\/p><p>void setup() {<br \/>pinMode(MuteSound, OUTPUT);\/\/ GPIO 0 is connected to the SD terminal of the amplifier chip<br \/>digitalWrite(MuteSound, LOW); \/\/ mute sound during startup<br \/><br \/>Serial.begin(115200);<br \/><br \/>\/\/ LED setup<br \/>left_LED.pins[0] = 16; left_LED.pins[1] = 17; left_LED.pins[2] = 5; left_LED.pins[3] = 18; \/\/ R, G, B, PWM ports<br \/>left_LED.channel = 0;<br \/>right_LED.pins[0] = 19; right_LED.pins[1] = 21; right_LED.pins[2] = 22; right_LED.pins[3] = 23; \/\/ R, G, B, PWM ports<br \/>right_LED.channel = 1;<br \/>\/\/ CATHODE RGB SETUP, 18 and 23 WILL BE PWM FOR DIMMING THE LED<br \/>pinMode(left_LED.pins[0], OUTPUT); pinMode(left_LED.pins[1], OUTPUT); pinMode(left_LED.pins[2], OUTPUT);<br \/>pinMode(right_LED.pins[0], OUTPUT); pinMode(right_LED.pins[1], OUTPUT); pinMode(right_LED.pins[2], OUTPUT);<br \/><br \/>\/\/ configure LED PWM functionalitites<br \/>ledcSetup(left_LED.channel, 5000, 8); \/\/ledchannel 0, frequency 5000 and resolution 8<br \/>ledcSetup(right_LED.channel, 5000, 8); \/\/ledchannel 1, frequency 5000 and resolution 8<br \/><br \/>\/\/ attach the channel to the GPIO to be controlled<br \/>ledcAttachPin(left_LED.pins[3], left_LED.channel); \/\/ connect pin 18 with led channel 0<br \/>ledcAttachPin(right_LED.pins[3], right_LED.channel); \/\/ connect pin 23 with led channel 1<\/p><p>Set_color( left_LED, RGB_pink, default_intensity, right_LED, RGB_pink, default_intensity);<br \/><br \/><br \/>\/\/ START PORTAL <br \/>NodeUitGans();<br \/>Set_color( left_LED, RGB_blue, default_intensity, right_LED, RGB_blue, default_intensity);<br \/>}<\/p><p><br \/>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/MAIN LOOP\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<\/p><p>void loop() {<\/p><p>if (Play_nr_Fapgans ==0) { \/\/ while playing the fapgans sound, all other loops should be interupted <br \/>digitalWrite(MuteSound, LOW); \/\/ mute sound until palying sound<br \/>remaining_delay = 10000; \/\/ msec delay. This set the cycle time of the loop<br \/>if ((String(Connect_to_node)==&#8221;Y&#8221;) or (String(Connect_to_node)==&#8221;y&#8221;)) {<br \/>\/\/ Check info from node<br \/>if(getinfo()) {<br \/>\/\/ No connection to node<br \/>Serial.println(&#8220;Not connected to client&#8221;);<br \/>Set_color( left_LED, RGB_red, default_intensity, right_LED, RGB_red, default_intensity);<br \/>}<br \/>else {<br \/>Serial.println(String(&#8220;Node alias : &#8220;)+ String(lnd_Alias));<br \/>if (!lnd_Synced){<br \/>Serial.println(String(&#8220;Synced_to_chain : no&#8221;));<br \/>Set_color( left_LED, RGB_pink, default_intensity, right_LED, RGB_pink, default_intensity);<br \/>}<br \/>else{<br \/>Serial.println(String(&#8220;Synced_to_chain : yes&#8221;));<br \/>Serial.println(String(&#8220;Block height : &#8220;+ String(block_Height)));<br \/>if (block_Height &gt; old_block_height) {<br \/>Set_color( left_LED, RGB_blue, max_intensity, right_LED, RGB_blue, max_intensity);<br \/>old_block_height = block_Height;<br \/>delay(3000);<br \/>}<br \/>\/\/ Node connected and synced<br \/>Set_color( left_LED, RGB_green, default_intensity, right_LED, RGB_green, default_intensity);<br \/>if (GetOnChain()) {<br \/>\/\/ could not get onchain balance<br \/>Serial.println(&#8220;Could not get onchain balance&#8221;);<br \/>Set_color( left_LED, RGB_red, default_intensity, right_LED, RGB_red, default_intensity);<br \/>}<br \/>Serial.println(String(&#8220;Onchain balance : &#8220;)+ String(onchain_balance));<br \/>if (initial_startup) {<br \/>\/\/ get the last settled invoice index. This is used to check if the LND balance is higher <br \/>\/\/ due to lower chanel closing fees (substracted from tyour balance) or a new invoice is paid.<br \/>if(getlastinvoicesettleindex()){Serial.println(&#8220;Could not get last invoice settle index&#8221;);}<br \/>}<br \/>if (GetLnd()) {<br \/>\/\/ could not get onchain balance<br \/>Serial.println(&#8220;Could not get lnd balance&#8221;);<br \/>Set_color( left_LED, RGB_red, default_intensity, right_LED, RGB_red, default_intensity);<br \/>}<br \/>Serial.println(String(&#8220;LND balance : &#8220;)+ String(lnd_balance));<br \/>if (onchainIsHigher or lndIsHigher) {<br \/>\/\/ you got paid<br \/>disco();<br \/>remaining_delay=0;<br \/>}<br \/>if (onchainIsLower or lndIsLower) {<br \/>RedBlink();<br \/>remaining_delay=0;<br \/>}<br \/>} <br \/>}<br \/>}<\/p><p>blink(); \/\/ random blink with one eye<br \/><br \/>\/\/** get price of BTC<br \/>if( getprice(USD_price)) {<br \/>Serial.println(&#8220;Could not get price from Coingecko&#8221;);<br \/>Set_color( left_LED, RGB_red, default_intensity, right_LED, RGB_red, default_intensity);<br \/>} <br \/>else {<br \/>\/\/ new price from Coingecko received<br \/>Set_color( left_LED, RGB_green, default_intensity, right_LED, RGB_green, default_intensity);<br \/>Serial.println(String(&#8220;Bitcoin price : &#8220;)+ String(USD_price));<br \/>String temp_string=&#8221;false&#8221;; if(has_been_significantly_lower) {temp_string = &#8220;true&#8221;;}<br \/>Serial.println(String(&#8220;Been sign lower : &#8220;)+ temp_string);<br \/>Serial.println(String(&#8220;Bitcoin ATH : &#8220;)+ String(btc_ATH));<br \/>Serial.println(String(&#8220;Bitcoin fapgans : &#8220;)+ String(btc_fapgans));<br \/>if (!has_been_significantly_lower and (USD_price &lt; (btc_ATH &#8211; ATH_threshold))) { has_been_significantly_lower=true;}<br \/>if ((((USD_price &gt; btc_ATH) and has_been_significantly_lower) or (USD_price &gt; (btc_ATH + ATH_threshold))) and USD_price &lt; btc_fapgans) {<br \/>\/\/ only ATH when price has been below threshold in past, or has risen for more than the threshold. Also ignore ATH when fapgans.<br \/>\/\/ ALL TIME HIGHT BTC PRICE IN USD<br \/>Serial.println(String(&#8220;All TIME HIGH : &#8220;)+ String(USD_price));<br \/>BlueBlink();<br \/>btc_ATH = USD_price;<br \/>itoa(btc_ATH,BTC_ATH,10);<br \/>SaveConfig(); \/\/ store new ATH<br \/>has_been_significantly_lower = false;<br \/>remaining_delay =0;<br \/>}<br \/>if (USD_price &gt;= btc_fapgans) {<br \/>\/\/ FAPGANS<br \/>Serial.println(String(&#8220;*** FAPGANS *** : &#8220;)+ String(USD_price) + &#8221; &gt;= &#8221; + String(btc_fapgans));<br \/>Play_nr_Fapgans = 5;<br \/>btc_fapgans = int(USD_price\/5000)*5000+5000;<br \/>btc_ATH = USD_price;<br \/>has_been_significantly_lower=false;<br \/>Serial.println(String(&#8220;New fapgans price: &#8220;)+ String(btc_fapgans));<br \/>itoa(btc_ATH,BTC_ATH,10);<br \/>itoa(btc_fapgans,BTC_fapgans,10);<br \/>SaveConfig(); \/\/ store new fapgans value<br \/>remaining_delay = 0;<br \/>}<br \/>} <br \/>delay(max(remaining_delay,0)); \/\/ when the processing time of above statement is shorter than the loop cycle time, it does an additional delay<br \/>old_onchain_balance = onchain_balance;<br \/>old_lnd_balance = lnd_balance;<br \/>lndIsHigher = false;<br \/>lndIsLower = false;<br \/>onchainIsHigher = false;<br \/>onchainIsLower = false;<br \/>if(initial_startup) { initial_startup = false;}<br \/>}<br \/>else { \/\/ play the fapgans sound<br \/>digitalWrite(MuteSound, HIGH); \/\/ un-mute sound<br \/>DacAudio.FillBuffer(); \/\/ Fill the sound buffer with data<br \/>if(GeeseHonk.Playing==false){ \/\/ if not playing,<br \/>Serial.println(&#8220;playing GeeseHonk&#8221;);<br \/>DacAudio.Play(&amp;GeeseHonk); \/\/ play it, this will cause it to repeat and repeat&#8230; <br \/>Play_nr_Fapgans&#8211;;<br \/>}<br \/>Fapgans(); \/\/ blink leds<br \/>}<br \/>\/\/ end of loop()<br \/>}<\/p><p><br \/>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/LED SEQUENCES\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<\/p><p>void Set_color( LED leftLED, int leftColor[3],int leftIntensity, LED rightLED, int rightColor[3],int rightIntensity) {<br \/>digitalWrite(leftLED.pins[0], leftColor[0]); digitalWrite(leftLED.pins[1], leftColor[1]); digitalWrite(leftLED.pins[2], leftColor[2]);<br \/>ledcWrite(leftLED.channel, 255-leftIntensity); \/\/left channel 0 to max led brightness (0-255)<br \/>digitalWrite(rightLED.pins[0], rightColor[0]); digitalWrite(rightLED.pins[1], rightColor[1]); digitalWrite(rightLED.pins[2], rightColor[2]);<br \/>ledcWrite(rightLED.channel, 255-rightIntensity); \/\/left channel 0 to max led brightness (0-255)<br \/>}<br \/>\/\/DISCO LOOP \/\/ you got paid<br \/>void disco(){<br \/>Serial.println(&#8220;DISCO&#8221;);<br \/>for (int i = 0; i &lt;= 15; i++) {<br \/>for (int intens=0; intens &lt;= 255; intens+=2) {<br \/>Set_color( left_LED, RGB_blue, intens, right_LED, RGB_blue, intens);<br \/>delay(2);<br \/>}<br \/>for (int intens=255; intens &gt;= 0; intens-=2) {<br \/>Set_color( left_LED, RGB_blue, intens, right_LED, RGB_blue, intens);<br \/>delay(2);<br \/>}<br \/>for (int intens=0; intens &lt;= 255; intens+=2) {<br \/>Set_color( left_LED, RGB_green, intens, right_LED, RGB_green, intens);<br \/>delay(2);<br \/>}<br \/>for (int intens=255; intens &gt;= 0; intens-=2) {<br \/>Set_color( left_LED, RGB_green, intens, right_LED, RGB_green, intens);<br \/>delay(2);<br \/>}<br \/>for (int intens=0; intens &lt;= 255; intens+=2) {<br \/>Set_color( left_LED, RGB_red, intens, right_LED, RGB_red, intens);<br \/>delay(2);<br \/>}<br \/>for (int intens=255; intens &gt;= 0; intens-=2) {<br \/>Set_color( left_LED, RGB_red, intens, right_LED, RGB_red, intens);<br \/>delay(2);<br \/>}<\/p><p>}<br \/>Set_color( left_LED, RGB_green, default_intensity, right_LED, RGB_green, default_intensity);<br \/>}<br \/>\/\/Red blink LOOP \/\/ you paid<br \/>void RedBlink(){<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>Set_color( left_LED, RGB_red, 0, right_LED, RGB_red, max_intensity);<br \/>delay(100);<br \/>Set_color( left_LED, RGB_red, max_intensity, right_LED, RGB_red, 0);<br \/>delay(100);<br \/>}<br \/>Set_color( left_LED, RGB_green, default_intensity, right_LED, RGB_green, default_intensity);<br \/>}<br \/>\/\/Blue blink LOOP \/\/ all time high<br \/>void BlueBlink(){<br \/>for (int i = 0; i &lt;= 7; i++) {<br \/>Set_color( left_LED, RGB_lime, max_intensity, right_LED, RGB_lime, max_intensity);<br \/>delay(200);<br \/>Set_color( left_LED, RGB_lime,0, right_LED, RGB_lime, 0);<br \/>delay(200);<br \/>Set_color( left_LED, RGB_lime, max_intensity, right_LED, RGB_lime, max_intensity);<br \/>delay(200);<br \/>Set_color( left_LED, RGB_lime,0, right_LED, RGB_lime, 0);<br \/>delay(200);<br \/>for (int intens=0; intens &lt;= 255; intens+=2) {<br \/>Set_color( left_LED, RGB_blue, intens, right_LED, RGB_blue, intens);<br \/>delay(10);<br \/>}<br \/>for (int intens=255; intens &gt;= 0; intens-=2) {<br \/>Set_color( left_LED, RGB_blue, intens, right_LED, RGB_blue, intens);<br \/>delay(10);<br \/>}<br \/>Set_color( left_LED, RGB_lime, max_intensity, right_LED, RGB_lime, max_intensity);<br \/>delay(200);<br \/>Set_color( left_LED, RGB_lime,0, right_LED, RGB_lime, 0);<br \/>delay(200);<br \/>Set_color( left_LED, RGB_lime, max_intensity, right_LED, RGB_lime, max_intensity);<br \/>delay(200);<br \/>Set_color( left_LED, RGB_lime,0, right_LED, RGB_lime, 0);<br \/>delay(200);<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>Set_color( left_LED, RGB_red, 0, right_LED, RGB_red, max_intensity);<br \/>delay(100);<br \/>Set_color( left_LED, RGB_red, max_intensity, right_LED, RGB_red, 0);<br \/>delay(100);<br \/>}<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>Set_color( left_LED, RGB_blue, 0, right_LED, RGB_blue, max_intensity);<br \/>delay(100);<br \/>Set_color( left_LED, RGB_blue, max_intensity, right_LED, RGB_blue, 0);<br \/>delay(100);<br \/>}<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>Set_color( left_LED, RGB_green, 0, right_LED, RGB_green, max_intensity);<br \/>delay(100);<br \/>Set_color( left_LED, RGB_green, max_intensity, right_LED, RGB_green, 0);<br \/>delay(100);<br \/>}<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>Set_color( left_LED, RGB_blue, 0, right_LED, RGB_blue, max_intensity);<br \/>delay(100);<br \/>Set_color( left_LED, RGB_blue, max_intensity, right_LED, RGB_blue, 0);<br \/>delay(100);<br \/>}<br \/>}<br \/>Set_color( left_LED, RGB_green, default_intensity, right_LED, RGB_green, default_intensity);<br \/>}<\/p><p>\/\/Fapgans LOOP <br \/>void Fapgans(){<br \/>int nr_cycles_per_led = 10;<br \/>if (i_fap &lt;= 1*nr_cycles_per_led) {<br \/>Set_color( left_LED, RGB_blue, 0, right_LED, RGB_blue, max_intensity);<br \/>}<br \/>else if (i_fap &lt;= 2*nr_cycles_per_led) {<br \/>Set_color( left_LED, RGB_blue, max_intensity, right_LED, RGB_blue, 0);<br \/>}<br \/>else if (i_fap &lt;= 3*nr_cycles_per_led) {<br \/>Set_color( left_LED, RGB_red, 0, right_LED, RGB_red, max_intensity);<br \/>}<br \/>else if (i_fap &lt;= 4*nr_cycles_per_led) {<br \/>Set_color( left_LED, RGB_red, max_intensity, right_LED, RGB_red, 0);<br \/>delay(10);<br \/>}<br \/>else if (i_fap &lt;= 5*nr_cycles_per_led) {<br \/>Set_color( left_LED, RGB_green, 0, right_LED, RGB_green, max_intensity);<br \/>}<br \/>else if (i_fap &lt;= 6*nr_cycles_per_led) {<br \/>Set_color( left_LED, RGB_green, max_intensity, right_LED, RGB_green, 0);<br \/>}<br \/>delay(10);<br \/>if(i_fap++ &gt;= 7*nr_cycles_per_led) {i_fap=0;}<br \/>}<br \/>void blink() {<br \/>\/\/ blink random with one eye<br \/>rnd = rand() % 1000;<br \/>if (rnd &lt;= 5) {<br \/>\/\/ dimm left LED<br \/>ledcWrite(left_LED.channel, 255-1); \/\/left channel 0 to max led brightness (0-255)<br \/>delay(5000);<br \/>ledcWrite(left_LED.channel, 255-default_intensity); \/\/left channel 0 to max led brightness (0-255)<br \/>remaining_delay -= 5000;<br \/>}<br \/>else if (rnd &gt;= 1000-5){<br \/>ledcWrite(right_LED.channel, 255-1); \/\/left channel 0 to max led brightness (0-255)<br \/>delay(5000);<br \/>ledcWrite(right_LED.channel, 255-default_intensity); \/\/left channel 0 to max led brightness (0-255)<br \/>remaining_delay -= 5000;<br \/>}<br \/>}<br \/>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/NODE CALLS\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>int GetOnChain() {<br \/>if (getonchainbalance()) {<br \/>Serial.println(&#8220;error onchain balance&#8221;);<br \/>return (1);<br \/>}<br \/>else {<br \/>\/\/ check if balance has changes<br \/>if ((onchain_balance &gt; old_onchain_balance) and !initial_startup) {<br \/>onchainIsHigher = true;<br \/>}<br \/>else if ((onchain_balance &lt; old_onchain_balance) and !initial_startup) {<br \/>onchainIsLower = true;<br \/>}<br \/>}<br \/>return (0);<br \/>}<\/p><p><br \/>int GetLnd() {<br \/>if (getlndbalance()) {Serial.println(&#8220;error lnd balance&#8221;); return (1); }<br \/>\/\/ check if balance has changes<br \/>if ((lnd_balance &gt; old_lnd_balance) and !initial_startup) {<br \/>\/\/ balance is higher, but could be caused by changing commit fees<br \/>if (getlastinvoicesettleindex()) {Serial.println(&#8220;Could not get last invoice settle index&#8221;); return (1); }<br \/>if (last_invoice_settle_index &gt; highest_invoice_settle_index) {<br \/>\/\/ **** somebody paid you *****<br \/>lndIsHigher = true;<br \/>Serial.println(String(&#8220;Old invoice settle index : &#8220;)+ String(highest_invoice_settle_index));<br \/>Serial.println(String(&#8220;New invoice settle index : &#8220;)+ String(last_invoice_settle_index));<br \/>highest_invoice_settle_index = last_invoice_settle_index;<br \/>}<br \/>}<br \/>else if ((lnd_balance &lt; old_lnd_balance) and !initial_startup) {<br \/>\/\/ balance is lower, but could be caused by changing commit fees<br \/>if (getlastpaymentsettleindex()) {Serial.println(&#8220;Could not get last payment settle index&#8221;); return (1); }<br \/>if (last_payment_index &gt; highest_payment_settle_index) {<br \/>\/\/ **** You paid somebody *****<br \/>lndIsLower = true;<br \/>Serial.println(String(&#8220;Old payment settle index : &#8220;)+ String(highest_payment_settle_index));<br \/>Serial.println(String(&#8220;New payment settle index : &#8220;)+ String(last_payment_index));<br \/>highest_payment_settle_index = last_payment_index; <br \/>}<br \/>}<br \/>return (0);<br \/>}<\/p><p><br \/>int getinfo() {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>const char* lnd_check;<br \/>bool synced_to_chain = false;<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>Serial.println(&#8220;error could not connect to client&#8221;);<br \/>return (1); <br \/>}<br \/>client.println(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/getinfo HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>const size_t capacity = JSON_OBJECT_SIZE(3) + 620;<br \/>DynamicJsonDocument doc(capacity);<br \/>deserializeJson(doc, content); <br \/>lnd_check = doc[&#8220;alias&#8221;];<br \/>if (!lnd_check){<br \/>return (1); <br \/>}<br \/>lnd_Alias = lnd_check;<br \/>synced_to_chain = doc[&#8220;synced_to_chain&#8221;];<br \/>block_Height = doc[&#8220;block_height&#8221;];<br \/>lnd_Synced = synced_to_chain;<br \/>\/\/ Serial.println(String(&#8220;alias : &#8220;)+ String(lndAlias));<br \/>return (0);<br \/>}<\/p><p>int getonchainbalance() {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>int new_confirmed_balance = 0;<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>delay(1000);<br \/>return (1); <br \/>}<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/balance\/blockchain HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>const size_t capacity = JSON_OBJECT_SIZE(3) + 620;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>new_confirmed_balance = doc[&#8220;confirmed_balance&#8221;];<br \/>onchain_balance = new_confirmed_balance;<br \/>\/\/Serial.println(&#8220;old_onchain_balance: &#8221; + String(confirmed_balance));<br \/>\/\/Serial.println(&#8220;new_onchain_balance: &#8221; + String(new_confirmed_balance));<br \/>return (0);<br \/>}<\/p><p><br \/><br \/>int getlndbalance() {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>int new_balance = 0;<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>return (1); <br \/>}<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/balance\/channels HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>const size_t capacity = JSON_OBJECT_SIZE(3) + 620;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>new_balance = doc[&#8220;balance&#8221;];<br \/>lnd_balance = new_balance;<br \/>\/\/Serial.println(&#8220;lnd_balance : &#8221; + String(new_balance));<br \/>return (0);<br \/>}<\/p><p><br \/>int getlastinvoicesettleindex() {<br \/>int invoicenr=0;<br \/>int settleindex;<br \/>if (getlastinvoice()) {<br \/>\/\/ error last invoice<br \/>Serial.println(&#8220;could not get last invoice&#8221;);<br \/>}<br \/>if (last_invoice_settle_index &gt; highest_invoice_settle_index) {<br \/>Serial.println(&#8220;Last invoice is new settled invoice&#8221;);<br \/>return (0);<br \/>}<br \/>else {<br \/>Serial.println(&#8220;Last innvoice is not settled&#8221;);<br \/>invoicenr=last_invoice-1; \/\/ the last invoice was not settled<br \/>while (invoicenr&#8211; &gt; 0) {<br \/>if (getinvoicebynumber(invoicenr, settleindex)) {<br \/>Serial.println(&#8220;getinvoicebynumber error&#8221;);<br \/>return (1);<br \/>}<br \/>if( settleindex &gt; highest_invoice_settle_index) {<br \/>\/\/ there is a settled invoice with a higher index<br \/>last_invoice_settle_index = settleindex;<br \/>Serial.println(&#8220;Last invoice is new settled invoice&#8221;);<br \/>break;<br \/>}<br \/>else if( settleindex !=0 and settleindex &lt;= highest_invoice_settle_index) {<br \/>\/\/ the indesx is lower, so no new settled invoice was found<br \/>Serial.println(&#8220;No new settled invoice found&#8221;);<br \/>break;<br \/>}<br \/>}<br \/>if (settleindex ==0){Serial.println(&#8220;No settled invoices found&#8221;);}<br \/>return (0);<br \/>} <br \/>}<br \/>int getlastinvoice() {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>const char* Is_Settled_tmp;<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>return (1); <br \/>}<br \/>\/\/ get the last invoice in order to get the last_index_offset<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/invoices?num_max_invoices=1&amp;reversed=true HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>\/\/Serial.println(&#8220;readstringuntil: &#8220;+String(content));<br \/>const size_t capacity = 2048;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>\/\/ serializeJsonPretty(doc, Serial);<br \/>last_invoice_settle_index = doc[&#8220;invoices&#8221;][0][&#8220;settle_index&#8221;];<br \/>last_invoice = doc[&#8220;last_index_offset&#8221;];<br \/>Serial.println(&#8220;Settle index : &#8221; + String(last_invoice_settle_index));<br \/>Serial.println(&#8220;Last invoice : &#8221; + String(last_invoice));<br \/>return (0);<br \/>}<\/p><p>int getinvoicebynumber(int invoicenr, int&amp; settleIndex) {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>return (1); <br \/>}<br \/>\/\/ get the invoice by index<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/invoices?num_max_invoices=1&amp;index_offset=&#8221;+invoicenr+&#8221; HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>\/\/ Serial.println(&#8220;readstringuntil: &#8220;+String(content));<br \/>const size_t capacity = 2048;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>settleIndex = doc[&#8220;invoices&#8221;][0][&#8220;settle_index&#8221;];<br \/>invoicenr = doc[&#8220;last_index_offset&#8221;];<br \/>Serial.println(&#8220;Invoice &#8220;+ String(invoicenr)+ &#8221; has settle_index &#8221; + String(settleIndex));<br \/>return (0);<br \/>}<\/p><p>\u00a0<\/p><p>\u00a0<\/p><p>int getlastpaymentsettleindex() {<br \/>int paymentnr=0;<br \/>String PaymentStatus=&#8221;&#8221;;<br \/>if (getlastpayment()) {<br \/>\/\/ error last payment<br \/>Serial.println(&#8220;could not get last payment&#8221;);<br \/>}<br \/>if (last_payment_status==&#8221;SUCCEEDED&#8221; and (last_payment_index &gt; highest_payment_settle_index)) {<br \/>Serial.println(&#8220;Last payment is new settled payment&#8221;);<br \/>return (0);<br \/>}<br \/>else {<br \/>Serial.println(&#8220;Last payment is not new or not higest settled&#8221;);<br \/>paymentnr=last_payment_index-1; \/\/ the last payment was not settled<br \/>while (paymentnr&#8211; &gt; 0) {<br \/>if (getpaymentbynumber(paymentnr, PaymentStatus)) {<br \/>Serial.println(&#8220;getpaymentbynumber error&#8221;);<br \/>return (1);<br \/>}<br \/>if( PaymentStatus==&#8221;SUCCEEDED&#8221; and (paymentnr &gt; highest_payment_settle_index)) {<br \/>\/\/ there is a succeeded payment with a higher index<br \/>last_payment_index = paymentnr;<br \/>Serial.println(&#8220;Last payment is new settled payment&#8221;);<br \/>break;<br \/>}<br \/>else if( paymentnr &lt;= highest_payment_settle_index) {<br \/>\/\/ the indesx is lower, so no new settled payment was found<br \/>Serial.println(&#8220;No new settled payment found&#8221;);<br \/>break;<br \/>}<br \/>}<br \/>if (paymentnr ==0){Serial.println(&#8220;No settled payments found&#8221;);}<br \/>return (0);<br \/>} <br \/>}<br \/>int getlastpayment() {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>const char* status_payment;<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>return (1); <br \/>}<br \/>\/\/ get the last payment in order to get the last_index_offset<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/payments?max_payments=1&amp;reversed=true HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>\/\/Serial.println(&#8220;readstringuntil: &#8220;+String(content));<br \/>const size_t capacity = 3072;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>\/\/serializeJsonPretty(doc, Serial);<br \/>status_payment = doc[&#8220;payments&#8221;][0][&#8220;status&#8221;];<br \/>last_payment_index = doc[&#8220;last_index_offset&#8221;];<br \/>last_payment_status = status_payment;<br \/>Serial.println(&#8220;Last payment status &#8221; + String(last_payment_status));<br \/>Serial.println(&#8220;Last payment : &#8221; + String(last_payment_index));<br \/>return (0);<br \/>}<\/p><p>int getpaymentbynumber(int paymentnr, String&amp; paymentstatus) {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>const char* lndserver = lnd_server;<br \/>const char* macaroon = lnd_macaroon;<br \/>const char* status_payment;<br \/>int lndport = atoi( lnd_port );<br \/>if (!client.connect(lndserver, lndport)){<br \/>return (1); <br \/>}<br \/>\/\/ get the payment by index<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + lndserver +&#8221;:&#8221;+ lndport + &#8220;\/v1\/payments?num_max_payments=1&amp;index_offset=&#8221;+paymentnr+&#8221; HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + lndserver +&#8221;:&#8221;+ lndport +&#8221;\\r\\n&#8221; +<br \/>&#8220;User-Agent: ESP322\\r\\n&#8221; +<br \/>&#8220;Grpc-Metadata-macaroon:&#8221; + macaroon + &#8220;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>client.stop();<br \/>\/\/ Serial.println(&#8220;readstringuntil: &#8220;+String(content));<br \/>const size_t capacity = 3072;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>status_payment= doc[&#8220;payments&#8221;][0][&#8220;status&#8221;];<br \/>paymentstatus = status_payment;<br \/>paymentnr = doc[&#8220;last_index_offset&#8221;];<br \/>Serial.println(&#8220;payment &#8220;+ String(paymentnr)+ &#8221; has status &#8221; + String(paymentstatus));<br \/>return (0);<br \/>}<\/p><p>\u00a0<\/p><p>\u00a0<\/p><p>int getprice(int&amp; USDprice) {<br \/>WiFiClientSecure client;<br \/>client.setInsecure();<br \/>const char* priceserver = price_server;<br \/>int priceport = atoi( price_port );<br \/>if (!client.connect(priceserver, priceport)){<br \/>delay(1000);<br \/>Serial.println(&#8220;not connected to coingecko for price info&#8221;);<br \/>return (1); <br \/>}<br \/>\/\/ Serial.println(&#8220;connected to coingecko for price info&#8221;);<br \/>client.print(String(&#8220;GET &#8220;)+ &#8220;https:\/\/&#8221; + priceserver +&#8221;:&#8221;+ priceport + &#8220;\/api\/v3\/simple\/price?ids=bitcoin&amp;vs_currencies=usd&amp;include_market_cap=false&amp;include_24hr_vol=false&amp;include_24hr_change=false&amp;include_last_updated_at=false HTTP\/1.1\\r\\n&#8221; +<br \/>&#8220;Host: &#8221; + priceserver +&#8221;:&#8221;+ priceport +&#8221;\\r\\n&#8221; +<br \/>&#8220;Content-Type: application\/json\\r\\n&#8221; +<br \/>&#8220;Connection: close\\r\\n&#8221; +<br \/>&#8220;\\n&#8221;);<\/p><p>\/\/ Serial.println(&#8220;request send to coingecko for price info&#8221;);<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>\/\/ Serial.println(&#8220;readstringuntil: &#8220;+String(line));<br \/>while (client.connected()) {<br \/>String line = client.readStringUntil(&#8216;\\n&#8217;);<br \/>\/\/ Serial.println(&#8220;readstringuntil: &#8220;+String(line));<br \/>if (line == &#8220;\\r&#8221; or line==&#8221;&#8221;) { <br \/>break;<br \/>}<br \/>}<br \/>String content = client.readStringUntil(&#8216;\\n&#8217;);<br \/>content = client.readStringUntil(&#8216;\\n&#8217;); \/\/ extra read is required in this case<br \/>client.stop();<br \/>\/\/ Serial.println(&#8220;content: &#8221; + content);<br \/>const size_t capacity = JSON_OBJECT_SIZE(3) + 620;<br \/>DynamicJsonDocument doc(capacity);<br \/>DeserializationError err=deserializeJson(doc, content);<br \/>if (err) {<br \/>Serial.println(&#8220;json error: &#8220;+String(err.f_str()));<br \/>return (1);<br \/>}<br \/>USDprice = doc[&#8220;bitcoin&#8221;][&#8220;usd&#8221;];<br \/>\/\/ USDprice = new_Price;<br \/>\/\/ Serial.println(&#8220;new price: &#8221; + String(USDprice));<br \/>return (0);<br \/>}<\/p><p>void NodeUitGans(){<\/p><p>WiFiManager wm;<br \/>Serial.println(&#8220;mounting FS&#8230;&#8221;);<br \/>while(!SPIFFS.begin(true)){<br \/>Serial.println(&#8220;failed to mount FS&#8221;);<br \/>delay(200);<br \/>}<\/p><p>\/\/CHECK IF RESET IS TRIGGERED\/WIPE DATA<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>\/\/ get touch read a number of times to get stable reading<br \/>Serial.println(&#8220;touchRead :&#8221; + String(touchRead(4)));<br \/>}<br \/>for (int i = 0; i &lt;= 5; i++) {<br \/>if(touchRead(4) &lt; 55){<br \/>Serial.println(&#8220;Reset button pressed&#8221;);<br \/>File file = SPIFFS.open(&#8220;\/config.txt&#8221;, FILE_WRITE);<br \/>file.print(&#8220;placeholder&#8221;);<br \/>wm.resetSettings();<br \/>}<br \/>delay(1000);<br \/>}<\/p><p>\/\/MOUNT FS AND READ CONFIG.JSON<br \/>File file = SPIFFS.open(&#8220;\/config.txt&#8221;);<br \/><br \/>spiffing = file.readStringUntil(&#8216;\\n&#8217;);<br \/>spiffcontent = spiffing.c_str();<br \/>DynamicJsonDocument json(1024);<br \/>deserializeJson(json, spiffcontent);<br \/>if(String(spiffcontent) != &#8220;placeholder&#8221;){<br \/>strcpy(BTC_ATH, json[&#8220;btc_ath&#8221;]);<br \/>strcpy(BTC_fapgans, json[&#8220;btc_fapgans&#8221;]);<br \/>strcpy(Connect_to_node, json[&#8220;connect_to_node&#8221;]);<br \/>strcpy(lnd_server, json[&#8220;lnd_server&#8221;]);<br \/>strcpy(lnd_port, json[&#8220;lnd_port&#8221;]);<br \/>strcpy(lnd_macaroon, json[&#8220;lnd_macaroon&#8221;]);<br \/><br \/>}<\/p><p>\/\/ADD PARAMS TO WIFIMANAGER<br \/>wm.setSaveConfigCallback(saveConfigCallback);<br \/>WiFiManagerParameter custom_lnd_btc_ath(&#8220;btc_ath&#8221;, &#8220;Bitcoin price all time high in usd&#8221;, BTC_ATH, 16);<br \/>WiFiManagerParameter custom_lnd_btc_fapgans(&#8220;btc_fapgans&#8221;, &#8220;Bitcoin price next fapgans in usd&#8221;, BTC_fapgans, 16);<br \/>WiFiManagerParameter custom_lnd_con_node(&#8220;connect_node&#8221;, &#8220;Connect to your own node (Y\/N)&#8221;, Connect_to_node, 2);<br \/>WiFiManagerParameter custom_lnd_server(&#8220;server&#8221;, &#8220;LND server&#8221;, lnd_server, 40);<br \/>WiFiManagerParameter custom_lnd_port(&#8220;port&#8221;, &#8220;LND port&#8221;, lnd_port, 6);<br \/>WiFiManagerParameter custom_lnd_macaroon(&#8220;macaroon&#8221;, &#8220;LND readonly macaroon&#8221;, lnd_macaroon, 500);<br \/><br \/>wm.addParameter(&amp;custom_lnd_btc_ath);<br \/>wm.addParameter(&amp;custom_lnd_btc_fapgans);<br \/>wm.addParameter(&amp;custom_lnd_con_node);<br \/>wm.addParameter(&amp;custom_lnd_server);<br \/>wm.addParameter(&amp;custom_lnd_port);<br \/>wm.addParameter(&amp;custom_lnd_macaroon);<br \/><br \/><br \/>\/\/IF RESET WAS TRIGGERED, RUN PORTAL AND WRITE FILES<br \/>if (!wm.autoConnect(&#8220;\u26a1\u26a1Nodeuitgans\u26a1\u26a1&#8221;, &#8220;gakgakgak&#8221;)) {<br \/>Serial.println(&#8220;failed to connect and hit timeout&#8221;);<br \/>delay(3000);<br \/>ESP.restart();<br \/>delay(5000);<br \/>}<br \/>Serial.println(&#8220;connected :)&#8221;);<br \/>strcpy(BTC_ATH, custom_lnd_btc_ath.getValue());<br \/>strcpy(BTC_fapgans, custom_lnd_btc_fapgans.getValue());<br \/>strcpy(Connect_to_node, custom_lnd_con_node.getValue());<br \/>strcpy(lnd_server, custom_lnd_server.getValue());<br \/>strcpy(lnd_port, custom_lnd_port.getValue());<br \/>strcpy(lnd_macaroon, custom_lnd_macaroon.getValue());<br \/>btc_ATH = atoi(BTC_ATH);<br \/>btc_fapgans = atoi(BTC_fapgans);<br \/>if (shouldSaveConfig) {<br \/>SaveConfig();<br \/>shouldSaveConfig = false;<br \/>}<\/p><p>Serial.println(&#8220;local ip&#8221;);<br \/>Serial.println(WiFi.localIP());<br \/>Serial.println(WiFi.gatewayIP());<br \/>Serial.println(WiFi.subnetMask());<br \/>}<\/p><p>\u00a0<\/p><p>void SaveConfig() {<br \/>Serial.println(&#8220;saving config&#8221;);<br \/>DynamicJsonDocument json(1024);<br \/>json[&#8220;btc_ath&#8221;] = BTC_ATH;<br \/>json[&#8220;btc_fapgans&#8221;] = BTC_fapgans;<br \/>json[&#8220;connect_to_node&#8221;] = Connect_to_node;<br \/>json[&#8220;lnd_server&#8221;] = lnd_server;<br \/>json[&#8220;lnd_port&#8221;] = lnd_port;<br \/>json[&#8220;lnd_macaroon&#8221;] = lnd_macaroon;<\/p><p><br \/>File configFile = SPIFFS.open(&#8220;\/config.txt&#8221;, &#8220;w&#8221;);<br \/>if (!configFile) {<br \/>Serial.println(&#8220;failed to open config file for writing&#8221;);<br \/>}<br \/>serializeJsonPretty(json, Serial);<br \/>serializeJson(json, configFile);<br \/>configFile.close();<br \/>}<\/p><p>void saveConfigCallback () {<br \/>Serial.println(&#8220;Should save config&#8221;);<br \/>shouldSaveConfig = true;<br \/>}<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-712a6f3 elementor-widget elementor-widget-text-editor\" data-id=\"712a6f3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Notes:<\/p><ul><li>05-11-2021: the software has been modified (a LND payment flashed the lights as if you got paid).<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-bcea7b5 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"bcea7b5\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-835fb49\" data-id=\"835fb49\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e7bb580 elementor-widget elementor-widget-text-editor\" data-id=\"e7bb580\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>I intended to add also a small actuator for the &#8220;fapping&#8221; effect, but the power supply was already a problem, so this was a no go.<\/p><p>On the right hand side, you can find the final software. Since the software is rather messy (understatement), feel free to improve the software.<\/p><p>Furthermore, you can see the resulting goose with green laser eyes.<\/p><p>Enjoy your Nodeuitgans!<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-14e3afb\" data-id=\"14e3afb\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-cde4b3b elementor-widget elementor-widget-image\" data-id=\"cde4b3b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.lightninglouk.nl\/wp-content\/uploads\/elementor\/thumbs\/Nooduitgans-e1634680421318-petb0sgazilbwznc42mx1mizg1flcmw7ljsorcj6kg.png\" title=\"Nooduitgans\" alt=\"Nooduitgans\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-50bbb87 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"50bbb87\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-48550245 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"48550245\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-7f41942a\" data-id=\"7f41942a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b0955a0 elementor-align-left elementor-widget elementor-widget-button\" data-id=\"b0955a0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-xs\" href=\"https:\/\/www.lightninglouk.nl\/index.php\/esp32-node-monitor-page-4\/\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Previous page<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-bde8a9e\" data-id=\"bde8a9e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>ESP32 node monitor Previous page Step 9 ESP32 on a breadboard On the right, you see the first attempt. I managed to get the first common cathode led burning green after checking my node. One the first led was fired-up, a second led was a piece of cake. Changing the colors of the leds is&hellip; <a class=\"more-link\" href=\"https:\/\/www.lightninglouk.nl\/index.php\/esp32-node-monitor-page-1\/esp32-node-monitor-page-5\/\">Continue reading <span class=\"screen-reader-text\">ESP32 node monitor page 5<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":172,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-426","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/pages\/426","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/comments?post=426"}],"version-history":[{"count":185,"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/pages\/426\/revisions"}],"predecessor-version":[{"id":919,"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/pages\/426\/revisions\/919"}],"up":[{"embeddable":true,"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/pages\/172"}],"wp:attachment":[{"href":"https:\/\/www.lightninglouk.nl\/index.php\/wp-json\/wp\/v2\/media?parent=426"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}