{"id":8241,"date":"2025-03-15T15:27:51","date_gmt":"2025-03-15T14:27:51","guid":{"rendered":"https:\/\/willem.aandewiel.nl\/?p=8241"},"modified":"2025-03-26T12:45:31","modified_gmt":"2025-03-26T11:45:31","slug":"bibliotheken-om-het-leven-makkelijker-te-maken","status":"publish","type":"post","link":"https:\/\/willem.aandewiel.nl\/index.php\/2025\/03\/15\/bibliotheken-om-het-leven-makkelijker-te-maken\/","title":{"rendered":"Bibliotheken om het leven makkelijker te maken (part 1)"},"content":{"rendered":"\n<p>[ 1,237 keer bekeken \/ views ]<br><br>Iedereen die weleens een programma schrijft, maakt gebruik van bibliotheken en klassen (classes) om zijn software te ontwikkelen. Als je (in C of C++) een programma schrijft voor een Arduino- of Espressif-bordje, voeg je dergelijke bibliotheken toe met het <code>#include &lt;..&gt;<\/code>-statement. Deze bibliotheken fungeren vaak als black boxes waarvan je de interne werking niet hoeft te kennen of te begrijpen.<\/p>\n\n\n\n<p>Ik werk veel met Espressif-bordjes (ESP8266 en ESP32), omdat deze veel mogelijkheden bieden. Je kunt er eenvoudig een WiFi-verbinding mee maken (met de WiFi- of WiFiManager-bibliotheek). Met behulp van een ingebouwde WebServer (ook een standaardbibliotheek) kan ik het ontwikkelde programma \u2018besturen\u2019 en configureren. Daar heb je dan wel de nodige HTML, stylesheets en JavaScript bij nodig. Daarnaast is het bijna altijd handig om de juiste tijd via het Network Time Protocol (NTP) op te halen. Ook vind ik het prettig om mijn projecten te debuggen via het telnet-protocol, zodat ik met een tekstgebaseerde terminal verbinding met zo&#8217;n project kan maken. Hiervoor is de bibliotheek <em>TelnetStream<\/em> mijn favoriete keuze. De Espressif-bordjes bieden bovendien de mogelijkheid om een deel van het geheugen als opslag te gebruiken (als een soort harde-schijf). Wil je hiervan gebruik maken, dan is een systeem voor het beheren van deze opslag erg prettig. Hiervoor heb ik eerder al code ontwikkeld (g\u00e9\u00e9n bibliotheek omdat ik toen nog niet wist hoe dat moet) onder de naam FSmanager en FSexplorer.<\/p>\n\n\n\n<p>Al met al gebruik ik een behoorlijk aantal bibliotheken, die samen toch nog aardig wat code vereisen om deze bibliotheken optimaal in te zetten.<\/p>\n\n\n\n<p class=\"has-blue-color has-light-gray-background-color has-text-color has-background has-link-color wp-elements-11d818967cdfdb13a4fa8c422b787902\" style=\"font-size:21px\">En zoals altijd dacht ik: &#8220;Dit moet eenvoudiger kunnen&#8221;.<\/p>\n\n\n\n<p>Daarom ben ik begonnen met het ontwikkelen van drie bibliotheken die al het bovenstaande met eenvoudige stukjes code regelen. In drie posts zal ik deze bibliotheken en hun gebruik beschrijven:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Deel 1: Networking<\/li>\n\n\n\n<li>Deel 2: <a href=\"https:\/\/willem.aandewiel.nl\/index.php\/2025\/03\/17\/bibliotheken-om-het-leven-makkelijker-te-maken-part-2\/\">Single Page Application (de GUI)<\/a><\/li>\n\n\n\n<li>Deel 3: <a href=\"https:\/\/willem.aandewiel.nl\/index.php\/2025\/03\/25\/bibliotheken-om-het-leven-makkelijker-te-maken-part-3\/\">Filesystem Manager<\/a><\/li>\n<\/ul>\n\n\n\n<p>Dit is deel 1 en gaat dus over Networking.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Networking<\/h2>\n\n\n\n<p>Deze bibliotheek maakt het eenvoudig om je project met je WiFi modem (Access Point) te verbinden. Ben je eenmaal verbonden met WiFi dan maakt deze bibliotheek het mogelijk om nieuwe versies van je programma&#8217;s Over The Air (OTA) te flashen. Geen kabels meer nodig! Ook zal deze bibliotheek ervoor zorgen dat je je project niet alleen via het IP-adres kunt benaderen maar \u00f3\u00f3k via een opgegeven hostname (bijvoorbeeld &#8220;project.local&#8221;). Debug uitvoer kun je zowel via de seri\u00eble poort bekijken maar ook via telnet. Tenslotte heb je, zonder er iets extra&#8217;s voor te hoeven doen, ook de actuele (atoom) tijd tot je beschikking. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installatie PlatformIO<\/h2>\n\n\n\n<p>Werk je met VSCode\/PlatformIO dan hoef je alleen de link naar de repo in je platformio.ini bestand op te nemen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lib_deps = https:\/\/github.com\/mrWheel\/esp-networking<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Installatie Arduino IDE<\/h2>\n\n\n\n<p>Voor de Arduino IDE moet je de repo als &#8220;.zip&#8221; bestand downloaden. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/DownloadRepoAsZip.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"478\" src=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/DownloadRepoAsZip-1024x478.png\" alt=\"\" class=\"wp-image-8243\" srcset=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/DownloadRepoAsZip-1024x478.png 1024w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/DownloadRepoAsZip-300x140.png 300w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/DownloadRepoAsZip-768x358.png 768w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/DownloadRepoAsZip.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Het <code>esp-networking-main.zip<\/code> bestand moet je ergens op je computer bewaren.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SaveZipFile.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"567\" src=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SaveZipFile-1024x567.png\" alt=\"\" class=\"wp-image-8244\" srcset=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SaveZipFile-1024x567.png 1024w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SaveZipFile-300x166.png 300w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SaveZipFile-768x426.png 768w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SaveZipFile.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Start nu de Arduino IDE op en klik op [Sketch] en selecteer [Add .ZIP library&#8230;]<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/AddZipLibrary.png\"><img loading=\"lazy\" decoding=\"async\" width=\"935\" height=\"250\" src=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/AddZipLibrary.png\" alt=\"\" class=\"wp-image-8245\" srcset=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/AddZipLibrary.png 935w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/AddZipLibrary-300x80.png 300w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/AddZipLibrary-768x205.png 768w\" sizes=\"auto, (max-width: 935px) 100vw, 935px\" \/><\/a><\/figure>\n\n\n\n<p>Nu navigeer je naar de folder waar je het <code>esp-networking-main.zip<\/code> bestand eerder hebt opgeslagen ..<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SelectZipLibrary.png\"><img loading=\"lazy\" decoding=\"async\" width=\"830\" height=\"675\" src=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SelectZipLibrary.png\" alt=\"\" class=\"wp-image-8246\" srcset=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SelectZipLibrary.png 830w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SelectZipLibrary-300x244.png 300w, https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2025\/03\/SelectZipLibrary-768x625.png 768w\" sizes=\"auto, (max-width: 830px) 100vw, 830px\" \/><\/a><\/figure>\n\n\n\n<p>&#8230; en klik je op [Choose].<br>Installeer nu ook de volgende bibliotheken (als dat nog niet gebeurd is):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>WiFiManager<\/li>\n\n\n\n<li>ESP8266WiFi (voor esp8266) of WiFi (voor esp32)<\/li>\n\n\n\n<li>ESP8266mDNS (voor esp8266) of ESPmDNS (voor esp32)<\/li>\n\n\n\n<li>ArduinoOTA<\/li>\n<\/ul>\n\n\n\n<p>De bibliotheek is nu klaar om gebruikt te worden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Eenvoudig gebruik (basic)<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"Networking.h\"\n\nNetworking* network = nullptr;\nStream* debug = nullptr;\n\nvoid setup()\n{\n    network = new Networking();\n    \n    \/\/-- Parameters: hostname, resetWiFi pin, serial object, baud rate\n    debug = network->begin(\"my-esp\", 0, Serial, 115200);\n    \n    if (!debug)\n    {\n      \/\/-- Restart if connection fails\n      ESP.restart(); \n    }\n}\n\nvoid loop()\n{\n    \/\/-- Must be called in main loop\n    network->loop();\n    \n    \/\/-- Use debug stream for output\n    debug->println(\"Hello World\");\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Uitleg<\/h3>\n\n\n\n<p>In regel 1 vertellen we de compiler dat we de &#8220;Networking&#8221; bibliotheek gaan gebruiken.<br>Regel 3 zorgt dat we een pointer cre\u00ebren naar het Networking object.<br>Regel 4 maakt een pointer &#8220;debug&#8221; aan van het type Stream.<br>In regel 8 maken we een nieuw object &#8220;netwerk&#8221; aan van de klasse Networking.<br>Regel 10 is waar het allemaal om draait. We roepen de methode &#8220;begin()&#8221; aan met een aantal parameters.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>De eerste is de hostnaam, in dit geval &#8220;esp8266&#8221;<\/li>\n\n\n\n<li>De tweede is het nummer van een GPIO pin (in dit geval &#8220;0&#8221;). Als tijdens het opstarten deze GPIO pin &#8220;Laag&#8221; wordt gemaakt worden de WiFi credentials verwijderd en start het WiFi Manager portal op.<\/li>\n\n\n\n<li>De derde parameter geeft aan op welk seri\u00eble poort debug uitvoer wordt geschreven (naast de uitvoer naar de telnet client).<\/li>\n\n\n\n<li>De vierde parameter geeft de snelheid aan waarmee naar de seri\u00eble poort moet worden geschreven.<\/li>\n\n\n\n<li>Er is ook nog een vijfde parameter maar die heeft standaard de waarde null.<\/li>\n<\/ul>\n\n\n\n<p>In de loop() functie moet de network-&gt;loop() functie worden aangeroepen om alles naar behoren te laten werken.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>WiFi Configuratie<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Eerste Opstart:<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Het apparaat maakt een Access Point aan met de naam van de <code>hostnaam<\/code>.<\/li>\n\n\n\n<li>Maak verbinding met dit AP via je telefoon\/computer.<\/li>\n\n\n\n<li>Configureer je WiFi-instellingen via het captive portal.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>WiFi Instellingen Reset:<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Houd de <code>resetWiFiPin<\/code> laag tijdens de opstart.<\/li>\n\n\n\n<li>WiFi-instellingen worden gewist.<\/li>\n\n\n\n<li>Het apparaat gaat terug naar de AP-modus voor herconfiguratie.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Remote Debugging<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Verbinden via Telnet:<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">telnet apparaat-ip-adres<\/pre>\n\n\n\n<p>Standaard poort: 23<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Verbinden via netcat (nc):<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">nc apparaat-ip-adres 23<\/pre>\n\n\n\n<p>Of gebruik in plaats van <code>apparaat-ip-adres<\/code> de mDNS-naam hostnaam.local.<\/p>\n\n\n\n<p><strong>Kenmerken:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Alle debug-uitvoer wordt zowel naar de seri\u00eble poort als naar Telnet geprint.<\/li>\n\n\n\n<li>Slechts \u00e9\u00e9n telnet-sessies wordt ondersteund (gelijktijdig).<\/li>\n\n\n\n<li>Automatisch sessiebeheer.<\/li>\n<\/ul>\n\n\n\n<p><strong>Uitgebreid Gebruik van OTA en WiFiManager<\/strong><\/p>\n\n\n\n<p>De bibliotheek biedt callbackfuncties voor OTA (Over-The-Air) update-evenementen en WiFiManager portal-activatie, waarmee je aangepaste code kunt uitvoeren op specifieke momenten:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void setup()\n{\n    network = new Networking();\n    debug = network->begin(\"my-esp\", 0, Serial, 115200);\n    \n    \/\/-- Registreer OTA callbacks\n    network->doAtStartOTA([]() \n    {\n        \/\/-- Aangeroepen wanneer de OTA-update begint\n        digitalWrite(LED_BUILTIN, LOW);  \/\/-- Zet LED aan\n        debug->println(\"OTA-update begint...\");\n    });\n    \n    network->doAtProgressOTA([]() \n    {\n        \/\/-- Aangeroepen bij elke 20% voortgang\n        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));  \/\/-- Wissel LED\n        debug->println(\"OTA: Nog eens 20% voltooid\");\n    });\n    \n    network->doAtEndOTA([]() \n    {\n        \/\/-- Aangeroepen wanneer de OTA-update bijna eindigt\n        digitalWrite(LED_BUILTIN, HIGH);  \/\/-- Zet LED uit\n        debug->println(\"OTA-update eindigt...\");\n    });\n\n    \/\/-- Registreer WiFiManager callback\n    network->doAtWiFiPortalStart([]() \n    {\n        \/\/-- Aangeroepen wanneer het WiFiManager portal is gestart (geen geldig SSID gevonden)\n        digitalWrite(LED_BUILTIN, LOW);  \/\/-- Zet LED aan\n        debug->println(\"WiFi-configuratie portal gestart\");\n    });\n}<\/pre>\n\n\n\n<p>Met deze callbacks kun je:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Het apparaat voorbereiden wanneer een update start (bijvoorbeeld kritieke gegevens opslaan, lopende processen stoppen).<\/li>\n\n\n\n<li>De voortgang monitoren bij 20%-intervallen (bijvoorbeeld een display bijwerken, indicatoren wisselen).<\/li>\n\n\n\n<li>Opruimoperaties uitvoeren voordat de update wordt afgerond.<\/li>\n\n\n\n<li>Visuele feedback geven tijdens updates met LED\u2019s of displays.<\/li>\n\n\n\n<li>Update-voortgang loggen naar externe systemen of opslag.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Netwerkstatus<\/strong><\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">if (network->isConnected())\n{\n    debug->print(\"IP Adres: \");\n    debug->println(network->getIPAddressString());\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>NTP Tijdbeheer<\/strong><\/h2>\n\n\n\n<p>De bibliotheek biedt uitgebreide NTP (Network Time Protocol) functionaliteit met automatische synchronisatie:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void setup()\n{\n    network = new Networking();\n    debug = network->begin(\"my-esp\", 0, Serial, 115200);\n    \n    \/\/-- Start NTP met Amsterdam tijdzone\n    if (network->ntpStart(\"CET-1CEST,M3.5.0,M10.5.0\/3\"))\n    {\n        debug->println(\"NTP succesvol gestart\");\n    }\n\n    \/\/-- Optioneel: Gebruik aangepaste NTP-servers\n    const char* ntpServers[] = {\"time.google.com\", \"time.cloudflare.com\", nullptr};\n    network->ntpStart(\"CET-1CEST,M3.5.0,M10.5.0\/3\", ntpServers);\n}\n\nvoid loop()\n{\n    network->loop();  \/\/-- Verzorgt automatische NTP-synchronisatie elk uur\n\n    if (network->ntpIsValid())\n    {\n        debug->print(\"Huidige tijd: \");\n        debug->println(network->ntpGetDateTime());\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Kenmerken:<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Automatische synchronisatie elk uur.<\/li>\n\n\n\n<li>Ondersteuning voor tijdzones met POSIX tijdzone strings.<\/li>\n\n\n\n<li>Ondersteuning voor aangepaste NTP-servers.<\/li>\n\n\n\n<li>Tijdzone-wijzigingen zonder de standaardinstellingen te be\u00efnvloeden.<\/li>\n\n\n\n<li>Diverse tijdformaten (epoch, datum, tijd, datetime).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Tijdzones<\/strong><\/h3>\n\n\n\n<p>Tijdzones worden gespecificeerd met POSIX tijdzone strings. Veelgebruikte voorbeelden:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Centrale Europese Tijd: &#8220;CET-1CEST,M3.5.0,M10.5.0\/3&#8221;<\/li>\n\n\n\n<li>Oostelijke Tijd: &#8220;EST5EDT,M3.2.0,M11.1.0&#8221;<\/li>\n\n\n\n<li>UTC: &#8220;UTC0&#8221;<\/li>\n\n\n\n<li>Japan: &#8220;JST-9&#8221;<\/li>\n<\/ul>\n\n\n\n<p class=\"has-blue-color has-text-color has-background has-link-color wp-elements-1ba7682240465478a18b48682562700a\" style=\"background-color:#fbef6c\">Als je mij wil helpen om meer van dit soort posts te schrijven, overweeg dan om een kleine donatie te geven door op de knop hieronder te klikken.<br><!-- Begin PayPal Donations by https:\/\/www.tipsandtricks-hq.com\/paypal-donations-widgets-plugin -->\n\n<form action=\"https:\/\/www.paypal.com\/cgi-bin\/webscr\" method=\"post\" target=\"_blank\">\n    <div class=\"paypal-donations\">\n        <input type=\"hidden\" name=\"cmd\" value=\"_donations\" \/>\n        <input type=\"hidden\" name=\"bn\" value=\"TipsandTricks_SP\" \/>\n        <input type=\"hidden\" name=\"business\" value=\"Willem@Aandewiel.nl\" \/>\n        <input type=\"hidden\" name=\"return\" value=\"https:\/\/willem.aandewiel.nl\/index.php\/thank-you-for-your-donation\/\" \/>\n        <input type=\"hidden\" name=\"item_number\" value=\"Networking\" \/>\n        <input type=\"hidden\" name=\"rm\" value=\"0\" \/>\n        <input type=\"hidden\" name=\"currency_code\" value=\"EUR\" \/>\n        <input type=\"image\" style=\"cursor: pointer;\" src=\"https:\/\/willem.aandewiel.nl\/wp-content\/uploads\/2022\/09\/bmc-button-75.png\" name=\"submit\" alt=\"PayPal - The safer, easier way to pay online.\" \/>\n        <img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"https:\/\/www.paypalobjects.com\/en_US\/i\/scr\/pixel.gif\" width=\"1\" height=\"1\" \/>\n    <\/div>\n<\/form>\n<!-- End PayPal Donations -->\n<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h1 class=\"wp-block-heading\">Voorbeelden<\/h1>\n\n\n\n<p>Alle in deze post gepresenteerde code kun je vinden in de <code>examples<\/code> folder van de <a href=\"https:\/\/github.com\/mrWheel\/esp-networking\" target=\"_blank\" rel=\"noreferrer noopener\">github repository<\/a>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-blue-color has-alpha-channel-opacity has-blue-background-color has-background is-style-wide\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">ESP Networking Library API Documentation<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Wat is een API?<\/h2>\n\n\n\n<p>Een API (Application Programming Interface) is een set van duidelijk gedefinieerde methoden, functies en protocollen die ontwikkelaars kunnen gebruiken om met een bepaalde software of hardware te communiceren. Een API fungeert als een brug tussen verschillende softwarecomponenten, waardoor ze met elkaar kunnen communiceren zonder dat de ontwikkelaar de interne werking van elke component hoeft te begrijpen.<\/p>\n\n\n\n<p>In de context van deze bibliotheek biedt de API een eenvoudige manier om netwerkfunctionaliteit te implementeren in ESP8266\/ESP32 projecten, zonder dat u zich zorgen hoeft te maken over de complexe details van WiFi-verbindingen, OTA-updates, telnet-servers of NTP-tijdsynchronisatie.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Networking Library Overzicht<\/h2>\n\n\n\n<p>De ESP Networking bibliotheek biedt een uitgebreide set functies voor het beheren van netwerkverbindingen op ESP8266 en ESP32 microcontrollers. De bibliotheek vereenvoudigt het proces van:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>WiFi-verbinding en -configuratie<\/li>\n\n\n\n<li>Over-the-Air (OTA) firmware updates<\/li>\n\n\n\n<li>Telnet server voor externe debugging<\/li>\n\n\n\n<li>mDNS service discovery<\/li>\n\n\n\n<li>NTP tijdsynchronisatie<\/li>\n\n\n\n<li>Automatische WiFi-herverbinding<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Hoofdklassen<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Networking Klasse<\/h2>\n\n\n\n<p>De <code>Networking<\/code> klasse is de primaire interface voor alle netwerkfunctionaliteit.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Initialisatie<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Networking* network = new Networking();\nStream* debug = network->begin(\"my-esp\", 0, Serial, 115200);\n\n\/\/-- Optioneel: callback voor WiFi portal\nnetwork->doAtWiFiPortalStart([]() {\n  Serial.println(\"WiFi configuratie portal gestart\");\n});<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Belangrijke Methoden<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">begin(hostname, resetWiFiPin, serial, serialSpeed, wifiCallback)<\/h2>\n\n\n\n<p>Initialiseert de netwerkfunctionaliteit.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>hostname<\/code>: De naam waarmee het apparaat op het netwerk zichtbaar is<\/li>\n\n\n\n<li><code>resetWiFiPin<\/code>: GPIO-pin die gebruikt wordt om WiFi-instellingen te resetten (verbind met GND om te resetten)<\/li>\n\n\n\n<li><code>serial<\/code>: HardwareSerial object voor debug output<\/li>\n\n\n\n<li><code>serialSpeed<\/code>: Baudrate voor seri\u00eble communicatie<\/li>\n\n\n\n<li><code>wifiCallback<\/code>: Optionele callback functie die wordt aangeroepen wanneer de WiFi-configuratieportal start<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Voorbeeld: Initialisatie met callback voor WiFi portal\nStream* debug = network->begin(\"my-esp\", 0, Serial, 115200, []() {\n  Serial.println(\"WiFi configuratie portal gestart!\");\n  \/\/-- Hier kunt u bijvoorbeeld een LED laten knipperen\n});<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">loop()<\/h2>\n\n\n\n<p>Moet regelmatig worden aangeroepen in de hoofdlus van uw programma om netwerkgebeurtenissen af te handelen.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void loop() \n{\n  network->loop(); \/\/-- Verplicht voor correcte werking\n\n  \/\/-- Uw eigen code hier\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">WiFi-gerelateerde methoden<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Controleer of WiFi verbonden is\nif (network->isConnected()) \n{\n  Serial.println(\"Verbonden met WiFi\");\n}\n\n\/\/-- Verkrijg het IP-adres als IPAddress object\nIPAddress ip = network->getIPAddress();\n\n\/\/-- Verkrijg het IP-adres als string\nString ipStr = network->getIPAddressString();\nSerial.print(\"IP-adres: \");\nSerial.println(ipStr); \/\/-- Bijvoorbeeld: \"192.168.1.105\"\n\n\/\/-- Handmatig opnieuw verbinden met WiFi (indien nodig)\nnetwork->reconnectWiFi();<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">OTA Update Callbacks<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Registreer callbacks voor OTA-updates\nnetwork->doAtStartOTA([]() {\n  Serial.println(\"OTA update gestart\");\n  \/\/-- Bijvoorbeeld: schakel LED in om aan te geven dat update bezig is\n});\n\nnetwork->doAtProgressOTA([]() {\n  Serial.println(\"OTA update voortgang\");\n  \/\/-- Wordt ongeveer elke 20% aangeroepen\n});\n\nnetwork->doAtEndOTA([]() {\n  Serial.println(\"OTA update voltooid\");\n  \/\/-- Bijvoorbeeld: schakel LED uit\n});<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">NTP Tijdsynchronisatie<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Start NTP met tijdzone voor Amsterdam\nif (network->ntpStart(\"CET-1CEST,M3.5.0,M10.5.0\/3\")) \n{\n  Serial.println(\"NTP succesvol gestart\");\n}\n\n\/\/-- Optioneel: aangepaste NTP-servers opgeven\n\/\/ const char* ntpServers[] = {\"time.google.com\", \"time.cloudflare.com\", nullptr};\n\/\/ network->ntpStart(\"CET-1CEST,M3.5.0,M10.5.0\/3\", ntpServers);\n\n\/\/-- Controleer of NTP tijd geldig is\nif (network->ntpIsValid()) \n{\n  Serial.println(\"NTP tijd is geldig\");\n}\n\n\/\/-- Verkrijg huidige datum (YYYY-MM-DD)\nSerial.print(\"Datum: \");\nSerial.println(network->ntpGetDate()); \/\/-- Bijvoorbeeld: \"2025-03-15\"\n\n\/\/-- Verkrijg huidige tijd (HH:MM:SS)\nSerial.print(\"Tijd: \");\nSerial.println(network->ntpGetTime()); \/\/-- Bijvoorbeeld: \"14:30:25\"\n\n\/\/-- Verkrijg huidige datum en tijd (YYYY-MM-DD HH:MM:SS)\nSerial.print(\"Datum en tijd: \");\nSerial.println(network->ntpGetDateTime()); \/\/-- Bijvoorbeeld: \"2025-03-15 14:30:25\"\n\n\/\/-- Verkrijg epoch tijd (seconden sinds 1-1-1970)\ntime_t epoch = network->ntpGetEpoch();\nSerial.print(\"Epoch: \");\nSerial.println(epoch); \/\/-- Bijvoorbeeld: \"1742265025\"\n\n\/\/-- Verkrijg tijd in andere tijdzone (bijvoorbeeld New York)\nSerial.print(\"New York tijd: \");\nSerial.println(network->ntpGetDateTime(\"EST5EDT,M3.2.0,M11.1.0\"));\n\n\/\/-- Verkrijg gedetailleerde tijdinformatie als tm struct\nstruct tm timeInfo = network->ntpGetTmStruct();\nSerial.printf(\"Jaar: %d\\n\", timeInfo.tm_year + 1900);\nSerial.printf(\"Maand: %d\\n\", timeInfo.tm_mon + 1);\nSerial.printf(\"Dag: %d\\n\", timeInfo.tm_mday);\nSerial.printf(\"Uur: %d\\n\", timeInfo.tm_hour);\nSerial.printf(\"Minuut: %d\\n\", timeInfo.tm_min);\nSerial.printf(\"Seconde: %d\\n\", timeInfo.tm_sec);<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">MultiStream Klasse<\/h2>\n\n\n\n<p>De <code>MultiStream<\/code> klasse wordt intern gebruikt om output naar zowel de seri\u00eble poort als telnet clients te sturen. U hoeft deze klasse normaal gesproken niet direct te gebruiken, maar u kunt het <code>Stream*<\/code> object dat door <code>begin()<\/code> wordt geretourneerd gebruiken voor alle debug output.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Gebruik het debug object voor alle output\ndebug->println(\"Deze tekst verschijnt zowel op de seri\u00eble monitor als via telnet\");\ndebug->printf(\"Geformatteerde output: %d, %s\\n\", 42, \"tekst\");<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Volledige Voorbeelden<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Basis Voorbeeld<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"Networking.h\"\n\nNetworking* network = nullptr;\nStream* debug = nullptr;\n\nvoid setup() \n{\n  Serial.begin(115200);\n  delay(1000);\n\n  \/\/-- Initialiseer networki\n  network = new Networking();\n  debug = network->begin(\"my-esp\", 0, Serial, 115200);\n\n  if (!debug) \n  {\n    ESP.restart(); \/\/-- Herstart als verbinding mislukt\n  }\n\n  debug->println(\"Netwerk ge\u00efnitialiseerd!\");\n  debug->print(\"IP-adres: \");\n  debug->println(network->getIPAddressString());\n}\n\nvoid loop() \n{\n  \/\/-- Verplicht: verwerk netwerkgebeurtenissen\n  network->loop();\n\n  \/\/-- Uw code hier\n  static unsigned long lastTime = 0;\n  if (millis() - lastTime > 10000) \n  {\n    lastTime = millis();\n    debug->println(\"Hallo wereld!\");\n  }\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">NTP Voorbeeld<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"Networking.h\"\n\nNetworking* network = nullptr;\nStream* debug = nullptr;\n\nvoid setup() \n{\n  Serial.begin(115200);\n  delay(1000);\n\n  \/\/-- Initialiseer network\n  network = new Networking();\n  debug = network->begin(\"my-esp\", 0, Serial, 115200);\n\n  if (!debug) \n  {\n    ESP.restart();\n  }\n\n  \/\/-- Start NTP met Amsterdam tijdzone\n  if (network->ntpStart(\"CET-1CEST,M3.5.0,M10.5.0\/3\")) \n  {\n    debug->println(\"NTP gestart\");\n  }\n}\n\nvoid loop() \n{\n  network->loop();\n\n  \/\/-- Toon tijd elke 5 seconden\n  static unsigned long lastTime = 0;\n  if (millis() - lastTime > 5000) \n  {\n    lastTime = millis();\n\n    if (network->ntpIsValid()) \n    {\n      debug->print(\"Huidige tijd: \");\n      debug->println(network->ntpGetDateTime());\n    } \n    else \n    {\n      debug->println(\"Wachten op geldige tijd...\");\n    }\n  }\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">OTA Update Voorbeeld<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"Networking.h\"\n\nNetworking* network = nullptr;\nStream* debug = nullptr;\nbool updateInProgress = false;\n\nvoid setup() \n{\n  Serial.begin(115200);\n  delay(1000);\n\n  \/\/-- Initialiseer network\n  network = new Networking();\n\n  \/\/-- Registreer OTA callbacks\n  network->doAtStartOTA([]() {\n    updateInProgress = true;\n    digitalWrite(LED_BUILTIN, HIGH); \/\/-- LED aan tijdens update\n  });\n\n  network->doAtEndOTA([]() {\n    updateInProgress = false;\n    digitalWrite(LED_BUILTIN, LOW); \/\/-- LED uit na update\n  });\n\n  \/\/-- Start network\n  debug = network->begin(\"my-esp\", 0, Serial, 115200);\n\n  if (!debug) \n  {\n    ESP.restart();\n  }\n\n  pinMode(LED_BUILTIN, OUTPUT);\n  digitalWrite(LED_BUILTIN, LOW);\n\n  debug->println(\"Klaar voor OTA updates!\");\n  debug->print(\"IP-adres: \");\n  debug->println(network->getIPAddressString());\n}\n\nvoid loop() \n{\n  network->loop();\n\n  \/\/-- Normale werking wanneer geen update bezig is\n  if (!updateInProgress) \n  {\n    \/\/-- Uw code hier\n    delay(1000);\n    debug->println(\"Systeem draait normaal...\");\n  }\n}<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Geavanceerde Functies<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">WiFi Reset<\/h2>\n\n\n\n<p>De bibliotheek ondersteunt het resetten van WiFi-instellingen door een GPIO-pin laag te maken (verbinden met GND). Dit is handig als u uw apparaat naar een ander netwerk wilt verplaatsen.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Bij initialisatie, geef de reset pin op (hier GPIO 0)\ndebug = network->begin(\"my-esp\", 0, Serial, 115200);\n\n\/\/-- Als GPIO 0 laag is tijdens opstarten, worden WiFi-instellingen gewist\n\/\/-- en start de configuratie portal<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Telnet Server<\/h2>\n\n\n\n<p>De bibliotheek start automatisch een telnet server op poort 23. U kunt verbinding maken met het apparaat via telnet om debug output te zien en te monitoren zonder fysieke verbinding.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$ telnet my-esp.local\nVerbonden met my-esp.local.\nEscape character is '^]'.\nWelcome to [my-esp] Telnet Server!<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">mDNS Service Discovery<\/h2>\n\n\n\n<p>Het apparaat is vindbaar op het lokale netwerk via mDNS met de hostname die u opgeeft, gevolgd door &#8220;.local&#8221;. Bijvoorbeeld: &#8220;my-esp.local&#8221;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tijdzone Formaten<\/h2>\n\n\n\n<p>Voor NTP-tijdsynchronisatie gebruikt de bibliotheek POSIX tijdzone strings. Hier zijn enkele voorbeelden:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Amsterdam\/Nederland: <code>\"CET-1CEST,M3.5.0,M10.5.0\/3\"<\/code><\/li>\n\n\n\n<li>Londen\/UK: <code>\"GMT0BST,M3.5.0\/1,M10.5.0\"<\/code><\/li>\n\n\n\n<li>New York\/US Eastern: <code>\"EST5EDT,M3.2.0,M11.1.0\"<\/code><\/li>\n\n\n\n<li>Los Angeles\/US Pacific: <code>\"PST8PDT,M3.2.0,M11.1.0\"<\/code><\/li>\n\n\n\n<li>Tokyo\/Japan: <code>\"JST-9\"<\/code><\/li>\n\n\n\n<li>Sydney\/Australia: <code>\"AEST-10AEDT,M10.1.0,M4.1.0\/3\"<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Foutafhandeling en Betrouwbaarheid<\/h2>\n\n\n\n<p>De bibliotheek bevat ingebouwde mechanismen voor het automatisch opnieuw verbinden met WiFi bij verbindingsverlies. Als het maximale aantal herverbindingspogingen (standaard 5) wordt bereikt, zal het bordje herstarten.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/-- Controleer periodiek de verbindingsstatus\nif (!network->isConnected()) \n{\n  debug->println(\"WiFi-verbinding verloren!\");\n\n  \/\/-- De bibliotheek zal automatisch proberen opnieuw verbinding te maken\n  \/\/-- U kunt ook handmatig herverbinden:\n  network->reconnectWiFi();\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Compatibiliteit<\/h2>\n\n\n\n<p>De bibliotheek werkt met zowel ESP8266 als ESP32 platforms. Het biedt een consistente API over beide platforms, waardoor uw code gemakkelijk overdraagbaar is.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Licensie<\/h1>\n\n\n\n<p>This project is licensed under the MIT License &#8211; see the LICENSE file for details.<\/p>\n\n\n\n<div style=\"height:165px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>[ ] Iedereen die weleens een programma schrijft, maakt gebruik van bibliotheken en klassen (classes) om zijn software te ontwikkelen. Als je (in C of C++) een programma schrijft voor een Arduino- of Espressif-bordje, voeg je dergelijke bibliotheken toe met &hellip; <a href=\"https:\/\/willem.aandewiel.nl\/index.php\/2025\/03\/15\/bibliotheken-om-het-leven-makkelijker-te-maken\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,157,6,143,20],"tags":[180,181,179],"class_list":["post-8241","post","type-post","status-publish","format-standard","hentry","category-computer","category-esp32","category-esp8266","category-firmware","category-wifi","tag-bibliotheek","tag-library","tag-networking"],"views":1237,"_links":{"self":[{"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/posts\/8241","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/comments?post=8241"}],"version-history":[{"count":42,"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/posts\/8241\/revisions"}],"predecessor-version":[{"id":8399,"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/posts\/8241\/revisions\/8399"}],"wp:attachment":[{"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/media?parent=8241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/categories?post=8241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/willem.aandewiel.nl\/index.php\/wp-json\/wp\/v2\/tags?post=8241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}