munet Network Library for muwerk Scheduler
A muwerk network library supporting WiFi, NTP, OTA and MQTT for ESP8266 and ESP32 and serial links for all platforms
Loading...
Searching...
No Matches
net.h
1// net.h - the muwerk network
2
3#pragma once
4
5// #if defined(__ESP__)
6
7#include "ustd_platform.h"
8#include "ustd_array.h"
9#include "ustd_map.h"
10
11#include "scheduler.h"
12#include "sensors.h"
13#include "muwerk.h"
14#include "jsonfile.h"
15#include "heartbeat.h"
16#include "timeout.h"
17
18namespace ustd {
19
72class Net {
73 public:
74 const long NET_CONFIG_VERSION = 1;
75 enum Netstate { NOTDEFINED, NOTCONFIGURED, SERVING, CONNECTINGAP, CONNECTED };
76 enum Netmode { OFF, AP, STATION, BOTH };
77
78 private:
79 // hardware configuration
80 uint8_t signalLed;
81 bool signalLogic;
82
83 // active configuration
84 Netmode defaultMode;
85 bool defaultReboot;
86 ustd::jsonfile config;
87
88 // hardware info
89 String apmAddress;
90 String macAddress;
91 String deviceID;
92
93 // runtime control - state management
94 Netmode mode;
95 Netstate curState;
96 Netstate oldState;
97 ustd::heartbeat statePublisher = 30000;
98 // runtime control - station connection management
99 ustd::heartbeat connectionMonitor = 1000;
100 ustd::timeout connectTimeout = 15000;
101 unsigned int reconnectMaxRetries = 40;
102 bool bRebootOnContinuedFailure = true;
103 bool bOnceConnected;
104 int initialCounter;
105 int deathCounter;
106 // runtime control - wifi scanning
107 bool scanning = false;
108
109 // operating values - station
110 ustd::sensorprocessor rssival = ustd::sensorprocessor(20, 1800, 2.0);
111 // operating values - ap
112 unsigned int connections;
113
114 // muwerk task management
115 Scheduler *pSched;
116 int tID;
117
118 public:
119 Net(uint8_t signalLed = 0xff, bool signalLogic = false)
120 : signalLed(signalLed), signalLogic(signalLogic) {
141 oldState = NOTDEFINED;
142 curState = NOTCONFIGURED;
143 }
144
145 void begin(Scheduler *pScheduler, Netmode opmode = AP, bool restartOnMultipleFailures = true) {
163 initLed();
164 initHardwareAddresses();
165 readNetConfig(opmode, restartOnMultipleFailures);
166 initScheduler(pScheduler);
167 startServices();
168 }
169
170 void begin(Scheduler *pScheduler, String SSID, String password = "",
171 String hostname = "muwerk-${macls}", Netmode opmode = AP,
172 bool restartOnMultipleFailures = true) {
209 if (opmode != Netmode::AP && opmode != Netmode::STATION) {
210 DBG("ERROR: Wrong operation mode specified on Net::begin");
211 return;
212 }
213 initLed();
214 initHardwareAddresses();
215 initNetConfig(SSID, password, hostname, opmode, restartOnMultipleFailures);
216 initScheduler(pScheduler);
217 startServices();
218 }
219
220 private:
221 void initScheduler(Scheduler *pScheduler) {
222 pSched = pScheduler;
223 tID = pSched->add([this]() { this->loop(); }, "net");
224
225 pSched->subscribe(
226 tID, "net/network/get",
227 [this](String topic, String msg, String originator) { this->publishState(); });
228
229 pSched->subscribe(
230 tID, "net/network/control",
231 [this](String topic, String msg, String originator) { this->control(msg); });
232
233 pSched->subscribe(
234 tID, "net/networks/get",
235 [this](String topic, String msg, String originator) { this->requestScan(msg); });
236 }
237
238 void loop() {
239 if (mode == Netmode::OFF) {
240 return;
241 }
242 // radio specific state handling
243 switch (curState) {
244 case NOTDEFINED:
245 case NOTCONFIGURED:
246 // states with inactive radio
247 break;
248 case CONNECTINGAP:
249 case CONNECTED:
250 case SERVING:
251 // states with active radio
252 unsigned int conns = WiFi.softAPgetStationNum();
253 if (conns != connections) {
254 connections = conns;
255 pSched->publish("net/connections", String(connections));
256 }
257 break;
258 }
259 // individual per state handling
260 switch (curState) {
261 case NOTDEFINED:
262 break;
263 case NOTCONFIGURED:
264 if (statePublisher.beat()) {
265 publishState();
266 }
267 break;
268 case CONNECTINGAP:
269 if (WiFi.status() == WL_CONNECTED) {
270 curState = CONNECTED;
271 DBG("Connected to WiFi with ip address " + WiFi.localIP().toString());
272 configureTime();
273 return;
274 }
275 if (connectTimeout.test()) {
276 DBG("Timout connecting to WiFi " + WiFi.SSID());
277 if (bOnceConnected) {
278 if (bRebootOnContinuedFailure) {
279 --deathCounter;
280 }
281 if (deathCounter == 0) {
282 DBG("Final connection failure, restarting...");
283 if (bRebootOnContinuedFailure) {
284 ESP.restart();
285 }
286 }
287 DBG("Reconnecting...");
288 WiFi.reconnect();
289 connectTimeout.reset();
290 } else {
291 DBG("Retrying to connect...");
292 if (initialCounter > 0) {
293 if (bRebootOnContinuedFailure) {
294 --initialCounter;
295 }
296 WiFi.reconnect();
297 connectTimeout.reset();
298 curState = CONNECTINGAP;
299 } else {
300 DBG("Final connect failure, configuration invalid?");
301 curState = NOTCONFIGURED;
302 if (bRebootOnContinuedFailure) {
303 ESP.restart();
304 }
305 }
306 }
307 }
308 break;
309 case CONNECTED:
310 bOnceConnected = true;
311 deathCounter = reconnectMaxRetries;
312 if (connectionMonitor.beat()) {
313 if (WiFi.status() == WL_CONNECTED) {
314 long rssi = WiFi.RSSI();
315 if (rssival.filter(&rssi)) {
316 pSched->publish("net/rssi", String(rssi));
317 }
318 } else {
319 WiFi.reconnect();
320 curState = CONNECTINGAP;
321 connectTimeout.reset();
322 }
323 }
324 break;
325 case SERVING:
326 if (statePublisher.beat()) {
327 publishState();
328 }
329 break;
330 }
331
332 // react to state transition
333 if (curState != oldState) {
334 DBGP("Net State ");
335 DBGP(getStringFromState(oldState));
336 DBGP(" -> ");
337 DBGP(getStringFromState(curState));
338 if (curState == CONNECTED) {
339 DBGP(", RSSI: ");
340 DBG(WiFi.RSSI());
341 } else {
342 DBG();
343 }
344
345 // Turn the LED on when device is connecting to a WiFi
346 setLed(curState == CONNECTINGAP);
347
348 oldState = curState;
349 publishState();
350 }
351 // handle scanning
352 if (scanning) {
353 processScan(WiFi.scanComplete());
354 }
355 } // namespace ustd
356
357 void control(String msg) {
358 msg.toLowerCase();
359 if (msg == "on" || msg == "start") {
360 if (curState == Netstate::NOTDEFINED || curState == Netstate::NOTCONFIGURED) {
361 startServices();
362 }
363 } else if (msg == "off" || msg == "stop") {
364 stopServices();
365 } else if (msg == "restart") {
366 stopServices();
367 pSched->publish("net/network/control", "start");
368 }
369 }
370
371 void initNetConfig(String SSID, String password, String hostname, Netmode opmode,
372 bool restart) {
373 // initialize default values
374 defaultMode = opmode;
375 defaultReboot = restart;
376
377 String prefix = "net/" + getStringFromMode(opmode) + "/";
378
379 // prepare mode and device id
380 mode = opmode;
381 deviceID = macAddress;
382 deviceID.replace(":", "");
383
384 // generate hardcoded configuration
385 config.clear(false, true);
386 config.writeBool("net/hardcoded", true);
387 config.writeString("net/hostname", hostname);
388 config.writeString("net/mode", getStringFromMode(opmode));
389 config.writeString("net/deviceid", deviceID);
390 config.writeString(prefix + "SSID", SSID);
391 config.writeString(prefix + "password", password);
392 config.writeBool("net/station/rebootOnFailure", restart);
393 }
394
395 void readNetConfig(Netmode opmode, bool restart) {
396 // initialize default values
397 defaultMode = opmode;
398 defaultReboot = restart;
399
400 // handle config version migrations
401 long version = config.readLong("net/version", 0);
402 if (version == 0) {
403 if (config.exists("net/SSID")) {
404 // pre version configuration file found
405 migrateNetConfigFrom(config, version);
406 config.clear();
407 }
408 } else if (version < NET_CONFIG_VERSION) {
409 // regular migration
410 migrateNetConfigFrom(config, version);
411 config.clear();
412 }
413
414 // prepare mode and device id
415 mode = getModeFromString(config.readString("net/mode"), defaultMode);
416 deviceID = config.readString("net/deviceid");
417 if (deviceID == "") {
418 // initialize device id to mac address
419 deviceID = macAddress;
420 deviceID.replace(":", "");
421 config.writeString("net/deviceid", deviceID);
422 }
423 }
424
425 void cleanupNetConfig() {
426 // free up memory - we reload the configuration on demand...
427 if (!config.readBool("net/hardcoded", false)) {
428 // but only if the configuration is NOT hardcoded...
429 DBG("Freeing configuration...");
430 config.clear();
431 }
432 }
433
434 void migrateNetConfigFrom(ustd::jsonfile &sf, long version) {
435 if (version == 0) {
436 // convert the oldest version to the current version
437 ustd::jsonfile nf(false, true); // no autocommit, force new
438 nf.writeLong("net/version", NET_CONFIG_VERSION);
439 nf.writeString("net/mode", "station");
440 nf.writeString("net/hostname", sf.readString("net/hostname"));
441 nf.writeString("net/station/SSID", sf.readString("net/SSID"));
442 nf.writeString("net/station/password", sf.readString("net/password"));
443 ustd::array<JSONVar> services;
444 if (sf.readJsonVarArray("net/services", services)) {
445 for (unsigned int i = 0; i < services.length(); i++) {
446 DBG("Processing service " + String(i));
447 if (JSON.typeof(services[i]) == "object") {
448 if (JSON.typeof(services[i]["timeserver"]) == "string") {
449 String ntphost = (const char *)(services[i]["timeserver"]);
450 DBG("Found timeserver host entry: " + ntphost);
451 JSONVar host;
452 host[0] = (const char *)ntphost.c_str();
453 nf.writeJsonVar("net/services/ntp/host", host);
454 } else if (JSON.typeof(services[i]["dstrules"]) == "string") {
455 String dstrules = (const char *)(services[i]["dstrules"]);
456 DBG("Found timeserver dstrules entry: " + dstrules);
457 nf.writeString("net/services/ntp/dstrules", dstrules);
458 } else if (JSON.typeof(services[i]["mqttserver"]) == "string") {
459 String mqttserver = (const char *)(services[i]["mqttserver"]);
460 DBG("Found mqtt host entry: " + mqttserver);
461 ustd::jsonfile mqtt(false, true); // no autocommit, force new
462 mqtt.writeString("mqtt/host", mqttserver);
463 mqtt.writeBool("mqtt/alwaysRetained", true);
464 mqtt.commit();
465 }
466 } else {
467 DBG("Wrong service entry");
468 }
469 }
470 }
471 nf.commit();
472 }
473 // implement here future conversions
474 // else if ( version == 1 ) {
475 // }
476 // else if ( version == 2 ) {
477 // }
478 }
479
480 void startServices() {
481 mode = getModeFromString(config.readString("net/mode"), defaultMode);
482 wifiSetMode(mode);
483 switch (mode) {
484 case Netmode::OFF:
485 DBG("Network is disabled");
486 curState = Netstate::NOTCONFIGURED;
487 publishState();
488 break;
489 case Netmode::AP:
490 if (startAP()) {
491 curState = Netstate::SERVING;
492 }
493 break;
494 case Netmode::STATION:
495 if (startSTATION()) {
496 curState = Netstate::CONNECTINGAP;
497 }
498 break;
499 case Netmode::BOTH:
500 if (startSTATION()) {
501 curState = Netstate::CONNECTINGAP;
502 startAP();
503 }
504 break;
505 }
506 if (curState == Netstate::NOTCONFIGURED) {
507 DBG("Failed to start network services");
508 cleanupNetConfig();
509 }
510 }
511
512 void stopServices() {
513 switch (mode) {
514 case Netmode::OFF:
515 DBG("Network is disabled");
516 publishState();
517 break;
518 case Netmode::AP:
519 DBG("Stopping AP");
520 WiFi.softAPdisconnect(false);
521 break;
522 case Netmode::STATION:
523 DBG("Disconnecting from WiFi");
524 WiFi.disconnect(false);
525 break;
526 case Netmode::BOTH:
527 DBG("Disconnecting from WiFi and stopping AP");
528 WiFi.disconnect(false);
529 WiFi.softAPdisconnect(false);
530 break;
531 }
532 scanning = false;
533 connections = 0;
534 curState = Netstate::NOTCONFIGURED;
535 wifiSetMode(Netmode::OFF);
536 cleanupNetConfig();
537 }
538
539 bool startAP() {
540 // configure hostname
541 String hostname = replaceVars(config.readString("net/hostname", "muwerk-${macls}"));
542 wifiAPSetHostname(hostname);
543
544 // configure network
545 String address = config.readString("net/ap/address");
546 String netmask = config.readString("net/ap/netmask");
547 String gateway = config.readString("net/ap/gateway");
548 if (address.length() & netmask.length()) {
549 wifiSoftAPConfig(address, gateway, netmask);
550 }
551
552 // configure AP
553 String SSID = replaceVars(config.readString("net/ap/SSID", "muwerk-${macls}"));
554 if (!SSID.length()) {
555 SSID = replaceVars("muwerk-${macls}");
556 }
557 String password = config.readString("net/ap/password");
558 unsigned int channel = config.readLong("net/ap/channel", 1, 13, 1);
559 bool hidden = config.readBool("net/ap/hidden", false);
560 unsigned int maxConnections = config.readLong("net/ap/maxConnections", 1, 8, 4);
561 connections = 0;
562
563 DBG("Starting AP with SSID " + SSID + "...");
564 if (wifiSoftAP(SSID, password, channel, hidden, maxConnections)) {
565 wifiAPSetHostname(hostname);
566 DBG("AP Serving");
567 return true;
568 } else {
569 DBG("AP Failed");
570 return false;
571 }
572 }
573
574 bool startSTATION() {
575 // get connection parameters
576 String hostname = replaceVars(config.readString("net/hostname"));
577 String SSID = config.readString("net/station/SSID");
578 String password = config.readString("net/station/password");
579
580 // get network parameter
581 ustd::array<String> dns;
582 String address = config.readString("net/station/address");
583 String netmask = config.readString("net/station/netmask");
584 String gateway = config.readString("net/station/gateway");
585 config.readStringArray("net/services/dns/host", dns);
586
587 // read some cached values
588 connectTimeout = config.readLong("net/station/connectTimeout", 3, 3600, 15) * 1000;
589 reconnectMaxRetries = config.readLong("net/station/maxRetries", 1, 1000000000, 40);
590 bRebootOnContinuedFailure = config.readBool("net/station/rebootOnFailure", defaultReboot);
591
592 DBG("Connecting WiFi " + SSID);
593 wifiSetHostname(hostname);
594 if (wifiBegin(SSID, password)) {
595 deathCounter = reconnectMaxRetries;
596 initialCounter = reconnectMaxRetries;
597 bOnceConnected = false;
598 curState = CONNECTINGAP;
599 connectTimeout.reset();
600 if (!wifiConfig(address, gateway, netmask, dns)) {
601 DBG("Failed to set network configuration");
602 }
603 wifiSetHostname(hostname); // override dhcp option "host name"
604 configureTime();
605 return true;
606 }
607 return false;
608 }
609
610 // Buggy config*Time ESP8266 APIs assume api param char* remain valid indefinitly!
611 // Unresolved as of now: https://github.com/esp8266/Arduino/issues/7056
612 // Hence:
613 ustd::array<String> ntpHosts;
614 String ntpDstRules;
615
616 void configureTime() {
617 ntpDstRules = config.readString("net/services/ntp/dstrules");
618 config.readStringArray("net/services/ntp/host", ntpHosts);
619
620 if (ntpDstRules.length() && ntpHosts.length()) {
621 // configure ntp servers AND TZ variable
622 configTzTime(ntpDstRules.c_str(), ntpHosts[0].c_str(),
623 ntpHosts.length() > 1 ? ntpHosts[1].c_str() : nullptr,
624 ntpHosts.length() > 2 ? ntpHosts[2].c_str() : nullptr);
625 } else if (ntpHosts.length()) {
626 // configure ntp servers without TZ variable
627 configTime(0, 0, ntpHosts[0].c_str(),
628 ntpHosts.length() > 1 ? ntpHosts[1].c_str() : nullptr,
629 ntpHosts.length() > 2 ? ntpHosts[2].c_str() : nullptr);
630 } else if (ntpDstRules.length()) {
631 // configure only TZ variable
632 setenv("TZ", ntpDstRules.c_str(), 3);
633 } else {
634 // take from RTC?
635 }
636 }
637
638 void publishState() {
639 JSONVar net;
640
641 net["mode"] = getStringFromMode(mode);
642 net["mac"] = macAddress;
643
644 switch (curState) {
645 case NOTCONFIGURED:
646 net["state"] = "notconfigured";
647 break;
648 case CONNECTINGAP:
649 net["state"] = "connectingap";
650 net["SSID"] = WiFi.SSID();
651 break;
652 case CONNECTED:
653 net["state"] = "connected";
654 net["SSID"] = WiFi.SSID();
655 net["hostname"] = wifiGetHostname();
656 net["ip"] = WiFi.localIP().toString();
657 break;
658 case SERVING:
659 net["state"] = "serving";
660 net["hostname"] = wifiAPGetHostname();
661 break;
662 default:
663 net["state"] = "undefined";
664 break;
665 }
666 if (curState != NOTCONFIGURED && (mode == Netmode::AP || mode == Netmode::BOTH)) {
667 net["ap"]["mac"] = WiFi.softAPmacAddress();
668 net["ap"]["SSID"] = replaceVars(config.readString("net/ap/SSID", "muwerk-${macls}"));
669 net["ap"]["ip"] = WiFi.softAPIP().toString();
670 net["ap"]["connections"] = (int)connections;
671 }
672 String json = JSON.stringify(net);
673 pSched->publish("net/network", json);
674 }
675
676 void requestScan(String scantype = "async") {
677 bool async = true;
678 bool hidden = false;
679 for (String arg = shift(scantype, ','); arg.length(); arg = shift(scantype, ',')) {
680 arg.toLowerCase();
681 if (arg == "sync") {
682 async = false;
683 } else if (arg == "async") {
684 async = true;
685 } else if (arg == "hidden") {
686 hidden = true;
687 }
688 }
689 processScan(WiFi.scanNetworks(async, hidden));
690 }
691
692 void processScan(int result) {
693 switch (result) {
694 case WIFI_SCAN_RUNNING:
695 if (!scanning) {
696 DBG("WiFi scan running...");
697 scanning = true;
698 }
699 break;
700 case WIFI_SCAN_FAILED:
701 DBG("WiFi scan FAILED.");
702 publishScan(result);
703 scanning = false;
704 case 0:
705 DBG("WiFi scan succeeded: No network found.");
706 scanning = false;
707 publishScan(result);
708 break;
709 default:
710 DBGF("WiFi scan succeeded: %u networks found.\r\n", result);
711 scanning = false;
712 publishScan(result);
713 }
714 }
715
716 void publishScan(int result) {
717 JSONVar res;
718
719 res["result"] = result < 0 ? "error" : "ok";
720 res["networks"] = JSON.parse("[]");
721
722 for (int i = 0; i < result; i++) {
723 JSONVar network;
724
725 network["ssid"] = WiFi.SSID(i);
726 network["rssi"] = WiFi.RSSI(i);
727 network["channel"] = WiFi.channel(i);
728 network["encryption"] = getStringFromEncryption(WiFi.encryptionType(i));
729 network["bssid"] = WiFi.BSSIDstr(i);
730#ifndef __ESP32__
731 network["hidden"] = WiFi.isHidden(i);
732#endif
733 res["networks"][i] = network;
734 }
735 pSched->publish("net/networks", JSON.stringify(res));
736 }
737
738 void initLed() {
739 if (signalLed != 0xff) {
740 pinMode(signalLed, OUTPUT);
741 setLed(signalLogic); // Turn the LED off
742 }
743 }
744
745 void setLed(bool on) {
746 if (signalLed != 0xff) {
747 if (signalLogic) {
748 digitalWrite(signalLed, on ? HIGH : LOW);
749 } else {
750 digitalWrite(signalLed, on ? LOW : HIGH);
751 }
752 }
753 }
754
755 String replaceVars(String val) {
756 String hexAddress = macAddress;
757 hexAddress.replace(":", "");
758 val.replace("${mac}", hexAddress);
759 val.replace("${macls}", hexAddress.substring(6));
760 val.replace("${macfs}", hexAddress.substring(0, 5));
761 return val;
762 }
763
764 void initHardwareAddresses() {
765 WiFiMode_t currentMode = WiFi.getMode();
766 WiFi.mode(WIFI_AP_STA);
767 apmAddress = WiFi.softAPmacAddress();
768 macAddress = WiFi.macAddress();
769 WiFi.mode(currentMode);
770 }
771
772 Netmode getModeFromString(String val, Netmode defVal = AP) {
773 val.toLowerCase();
774 if (val == "ap") {
775 return AP;
776 } else if (val == "station") {
777 return STATION;
778 } else if (val == "both") {
779 return BOTH;
780 } else {
781 return defVal;
782 }
783 }
784
785 const char *getStringFromEncryption(int encType) {
786 // read the encryption type and print out the name:
787#if !defined(__ESP32__)
788 switch (encType) {
789 case ENC_TYPE_WEP:
790 return "WEP";
791 case ENC_TYPE_TKIP:
792 return "WPA";
793 case ENC_TYPE_CCMP:
794 return "WPA2";
795 case ENC_TYPE_NONE:
796 return "None";
797 case ENC_TYPE_AUTO:
798 return "Auto";
799 default:
800 return "unknown";
801 }
802#else
803 switch (encType) {
804 case WIFI_AUTH_OPEN:
805 return "None";
806 case WIFI_AUTH_WEP:
807 return "WEP";
808 case WIFI_AUTH_WPA_PSK:
809 return "WPA_PSK";
810 case WIFI_AUTH_WPA2_PSK:
811 return "WPA2_PSK";
812 case WIFI_AUTH_WPA_WPA2_PSK:
813 return "WPA_WPA2_PSK";
814 case WIFI_AUTH_WPA2_ENTERPRISE:
815 return "WPA2_ENTERPRISE";
816 default:
817 return "unknown";
818 }
819#endif
820 }
821
822 String getStringFromMode(Netmode val) {
823 switch (val) {
824 default:
825 case Netmode::OFF:
826 return "off";
827 case Netmode::AP:
828 return "ap";
829 case Netmode::STATION:
830 return "station";
831 case Netmode::BOTH:
832 return "both";
833 }
834 }
835
836 const char *getStringFromState(Netstate val) {
837 switch (val) {
838 default:
839 case Netstate::NOTDEFINED:
840 return "NOTDEFINED";
841 case Netstate::NOTCONFIGURED:
842 return "NOTCONFIGURED";
843 case Netstate::SERVING:
844 return "SERVING";
845 case Netstate::CONNECTINGAP:
846 return "CONNECTINGAP";
847 case Netstate::CONNECTED:
848 return "CONNECTED";
849 }
850 }
851
852 // ESP WiFi Abstraction
853
854 static String wifiGetHostname() {
855#if defined(__ESP32__)
856 return WiFi.getHostname();
857#else
858 return WiFi.hostname();
859#endif
860 }
861
862 void wifiSetHostname(String &hostname) {
863 if (!hostname.length()) {
864 hostname = replaceVars("muwerk-${macls}");
865 }
866#if defined(__ESP32__)
867 WiFi.setHostname(hostname.c_str());
868#else
869 WiFi.hostname(hostname.c_str());
870#endif
871 }
872
873#if !defined(__ESP32__)
874 // since the ESP8266 is not able to manage a hostname for the soft station network,
875 // we need to emulate it
876 static String esp8266APhostname;
877#endif
878
879 static String wifiAPGetHostname() {
880#if defined(__ESP32__)
881 return WiFi.softAPgetHostname();
882#else
883 return Net::esp8266APhostname;
884#endif
885 }
886
887 void wifiAPSetHostname(String &hostname) {
888 if (!hostname.length()) {
889 hostname = replaceVars("muwerk-${macls}");
890 }
891#if defined(__ESP32__)
892 WiFi.softAPsetHostname(hostname.c_str());
893#else
894 Net::esp8266APhostname = hostname;
895#endif
896 }
897
898 static bool wifiSoftAP(String ssid, String passphrase, unsigned int channel, bool hidden,
899 unsigned int max_connection) {
900#if defined(__ESP32__)
901 return WiFi.softAP(ssid.c_str(), passphrase.c_str(), channel, hidden, max_connection);
902#else
903 return WiFi.softAP(ssid, passphrase, channel, hidden, max_connection);
904#endif
905 }
906
907 static bool wifiSoftAPConfig(String &address, String &gateway, String &netmask) {
908 IPAddress addr;
909 IPAddress gate;
910 IPAddress mask;
911 addr.fromString(address);
912 mask.fromString(netmask);
913 if (gateway.length()) {
914 gate.fromString(gateway);
915 }
916 return WiFi.softAPConfig(addr, gate, mask);
917 }
918
919 static bool wifiConfig(String &address, String &gateway, String &netmask,
920 ustd::array<String> &dns) {
921 IPAddress addr;
922 IPAddress gate;
923 IPAddress mask;
924 IPAddress dns1;
925 IPAddress dns2;
926 if (address.length() && netmask.length()) {
927 DBG("Setting static ip: " + address + " " + netmask);
928 addr.fromString(address);
929 mask.fromString(netmask);
930 }
931 if (gateway.length()) {
932 DBG("Setting static gateway: " + gateway);
933 gate.fromString(gateway);
934 }
935 if (dns.length() > 0) {
936 DBG("Setting dns server 1: " + String(dns[0]));
937 dns1.fromString(dns[0]);
938 }
939 if (dns.length() > 1) {
940 DBG("Setting dns server 2: " + String(dns[1]));
941 dns2.fromString(dns[1]);
942 }
943 return WiFi.config(addr, gate, mask, dns1, dns2);
944 }
945
946 static bool wifiBegin(String &ssid, String &passphrase) {
947#if defined(__ESP32__)
948 return WiFi.begin(ssid.c_str(), passphrase.c_str());
949#else
950 return WiFi.begin(ssid, passphrase);
951#endif
952 }
953
954 static void wifiSetMode(Netmode val) {
955 switch (val) {
956 case Netmode::OFF:
957 WiFi.mode(WIFI_OFF);
958 break;
959 default:
960 case Netmode::AP:
961 WiFi.mode(WIFI_AP);
962 break;
963 case Netmode::STATION:
964 WiFi.mode(WIFI_STA);
965 break;
966 case Netmode::BOTH:
967 WiFi.mode(WIFI_AP_STA);
968 break;
969 }
970 }
971};
972
973#if !defined(__ESP32__)
974// since the ESP8266 is not able to manage a hostname for the soft station network,
975// we need to emulate it
976String Net::esp8266APhostname = "";
977#endif
978
979} // namespace ustd
980
981// #endif // defined(__ESP__)
munet, the muwerk network class for WiFi and NTP
Definition: net.h:72
void begin(Scheduler *pScheduler, Netmode opmode=AP, bool restartOnMultipleFailures=true)
Definition: net.h:145
void begin(Scheduler *pScheduler, String SSID, String password="", String hostname="muwerk-${macls}", Netmode opmode=AP, bool restartOnMultipleFailures=true)
Definition: net.h:170
Net(uint8_t signalLed=0xff, bool signalLogic=false)
Definition: net.h:119
The muwerk namespace.
Definition: mqtt.h:21