diff --git a/ArduinoUniqueID.cpp b/ArduinoUniqueID.cpp
new file mode 100644
index 0000000..08bcd69
--- /dev/null
+++ b/ArduinoUniqueID.cpp
@@ -0,0 +1,121 @@
+/*
+ * © 2020 Gregor Baues, Luiz Henrique Cassettari. All rights reserved.
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * See the GNU General Public License for more details
+ */
+#include "ArduinoUniqueID.h"
+
+ArduinoUniqueID::ArduinoUniqueID()
+{
+#if defined(ARDUINO_ARCH_AVR)
+ for (size_t i = 0; i < UniqueIDsize; i++)
+ {
+ id[i] = boot_signature_byte_get(0x0E + i + (UniqueIDsize == 9 && i > 5 ? 1 : 0));
+ }
+#elif defined(ARDUINO_ARCH_ESP8266)
+ uint32_t chipid = ESP.getChipId();
+ id[0] = 0;
+ id[1] = 0;
+ id[2] = 0;
+ id[3] = 0;
+ id[4] = chipid >> 24;
+ id[5] = chipid >> 16;
+ id[6] = chipid >> 8;
+ id[7] = chipid;
+
+#elif defined(ARDUINO_ARCH_ESP32)
+ uint64_t chipid = ESP.getEfuseMac();
+ id[0] = 0;
+ id[1] = 0;
+ id[2] = chipid;
+ id[3] = chipid >> 8;
+ id[4] = chipid >> 16;
+ id[5] = chipid >> 24;
+ id[6] = chipid >> 32;
+ id[7] = chipid >> 40;
+
+#elif defined(ARDUINO_ARCH_SAM)
+ unsigned int status ;
+ /* Send the Start Read unique Identifier command (STUI) by writing the Flash Command Register with the STUI command.*/
+ EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
+ do
+ {
+ status = EFC1->EEFC_FSR ;
+ } while ( (status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY ) ;
+
+ /* The Unique Identifier is located in the first 128 bits of the Flash memory mapping. So, at the address 0x400000-0x400003. */
+ uint32_t pdwUniqueID[4];
+ pdwUniqueID[0] = *(uint32_t *)IFLASH1_ADDR;
+ pdwUniqueID[1] = *(uint32_t *)(IFLASH1_ADDR + 4);
+ pdwUniqueID[2] = *(uint32_t *)(IFLASH1_ADDR + 8);
+ pdwUniqueID[3] = *(uint32_t *)(IFLASH1_ADDR + 12);
+ for (int i = 0; i < 4; i++)
+ {
+ id[i*4+0] = (uint8_t)(pdwUniqueID[i] >> 24);
+ id[i*4+1] = (uint8_t)(pdwUniqueID[i] >> 16);
+ id[i*4+2] = (uint8_t)(pdwUniqueID[i] >> 8);
+ id[i*4+3] = (uint8_t)(pdwUniqueID[i] >> 0);
+ }
+
+ /* To stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier
+ command (SPUI) by writing the Flash Command Register with the SPUI command. */
+ EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI ;
+
+ /* When the Stop read Unique Unique Identifier command (SPUI) has been performed, the
+ FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises. */
+ do
+ {
+ status = EFC1->EEFC_FSR ;
+ } while ( (status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY );
+
+#elif defined(ARDUINO_ARCH_SAMD)
+
+ // from section 9.3.3 of the datasheet
+ #define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
+ #define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
+ #define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
+ #define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)
+
+ uint32_t pdwUniqueID[4];
+ pdwUniqueID[0] = SERIAL_NUMBER_WORD_0;
+ pdwUniqueID[1] = SERIAL_NUMBER_WORD_1;
+ pdwUniqueID[2] = SERIAL_NUMBER_WORD_2;
+ pdwUniqueID[3] = SERIAL_NUMBER_WORD_3;
+
+ for (int i = 0; i < 4; i++)
+ {
+ id[i*4+0] = (uint8_t)(pdwUniqueID[i] >> 24);
+ id[i*4+1] = (uint8_t)(pdwUniqueID[i] >> 16);
+ id[i*4+2] = (uint8_t)(pdwUniqueID[i] >> 8);
+ id[i*4+3] = (uint8_t)(pdwUniqueID[i] >> 0);
+ }
+
+#elif defined(ARDUINO_ARCH_STM32)
+ uint32_t pdwUniqueID[3];
+ pdwUniqueID[0] = HAL_GetUIDw0();
+ pdwUniqueID[1] = HAL_GetUIDw1();
+ pdwUniqueID[2] = HAL_GetUIDw2();
+ for (int i = 0; i < 3; i++)
+ {
+ id[i*4+0] = (uint8_t)(pdwUniqueID[i] >> 24);
+ id[i*4+1] = (uint8_t)(pdwUniqueID[i] >> 16);
+ id[i*4+2] = (uint8_t)(pdwUniqueID[i] >> 8);
+ id[i*4+3] = (uint8_t)(pdwUniqueID[i] >> 0);
+ }
+#endif
+}
+
+ArduinoUniqueID _UniqueID;
\ No newline at end of file
diff --git a/ArduinoUniqueID.h b/ArduinoUniqueID.h
new file mode 100644
index 0000000..a5f9bbc
--- /dev/null
+++ b/ArduinoUniqueID.h
@@ -0,0 +1,104 @@
+/*
+ * © 2020 Gregor Baues, Luiz Henrique Cassettari. All rights reserved.
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * See the GNU General Public License for more details
+ */
+
+#ifndef _ARDUINO_UNIQUE_ID_H_
+#define _ARDUINO_UNIQUE_ID_H_
+
+#include
+
+#if defined(ARDUINO_ARCH_AVR)
+#include
+#ifndef SIGRD
+#define SIGRD 5
+#endif
+#elif defined(ARDUINO_ARCH_ESP8266)
+#elif defined(ARDUINO_ARCH_ESP32)
+#elif defined(ARDUINO_ARCH_SAM)
+#elif defined(ARDUINO_ARCH_SAMD)
+#elif defined(ARDUINO_ARCH_STM32)
+#else
+#error "ArduinoUniqueID only works on AVR, SAM, SAMD, STM32 and ESP Architecture"
+#endif
+
+#if defined(ARDUINO_ARCH_AVR)
+
+#if defined(__AVR_ATmega328PB__)
+#define UniqueIDsize 10
+#else
+#define UniqueIDsize 9
+#endif
+
+#define UniqueIDbuffer UniqueIDsize
+
+#elif defined(ARDUINO_ARCH_ESP8266)
+#define UniqueIDsize 4
+#define UniqueIDbuffer 8
+#elif defined(ARDUINO_ARCH_ESP32)
+#define UniqueIDsize 6
+#define UniqueIDbuffer 8
+#elif defined(ARDUINO_ARCH_SAM)
+#define UniqueIDsize 16
+#define UniqueIDbuffer 16
+#elif defined(ARDUINO_ARCH_SAMD)
+#define UniqueIDsize 16
+#define UniqueIDbuffer 16
+#elif defined(ARDUINO_ARCH_STM32)
+#define UniqueIDsize 12
+#define UniqueIDbuffer 12
+#endif
+
+#define UniqueID8 (_UniqueID.id + UniqueIDbuffer - 8)
+#define UniqueID (_UniqueID.id + UniqueIDbuffer - UniqueIDsize)
+
+#define UniqueIDdump(stream) \
+ { \
+ stream.print("UniqueID: "); \
+ for (size_t i = 0; i < UniqueIDsize; i++) \
+ { \
+ if (UniqueID[i] < 0x10) \
+ stream.print("0"); \
+ stream.print(UniqueID[i], HEX); \
+ stream.print(" "); \
+ } \
+ stream.println(); \
+ }
+
+#define UniqueID8dump(stream) \
+ { \
+ stream.print("UniqueID: "); \
+ for (size_t i = 0; i < 8; i++) \
+ { \
+ if (UniqueID8[i] < 0x10) \
+ stream.print("0"); \
+ stream.print(UniqueID8[i], HEX); \
+ stream.print(" "); \
+ } \
+ stream.println(); \
+ }
+
+class ArduinoUniqueID
+{
+ public:
+ ArduinoUniqueID();
+ uint8_t id[UniqueIDbuffer];
+};
+
+extern ArduinoUniqueID _UniqueID;
+
+#endif
\ No newline at end of file
diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino
index b717392..1c38758 100644
--- a/CommandStation-EX.ino
+++ b/CommandStation-EX.ino
@@ -86,7 +86,7 @@ void setup()
// nwi1.setup(ETHERNET, TCP); // ETHERNET/TCP on Port 2560
nwi2.setup(ETHERNET, TCP, 23); // ETHERNET/TCP on Port 23 for the CLI
// nwi1.setup(ETHERNET, TCP, 8888); // ETHERNET/TCP on Port 8888
- // nwi2.setup(WIFI, TCP); // WIFI/TCP on Port 2560
+ nwi2.setup(WIFI, TCP); // WIFI/TCP on Port 2560
// nwi1.setHttpCallback(httpRequestHandler); // HTTP callback
DIAG(F("\nNetwork Setup done ...\n"));
diff --git a/EthernetSetup.cpp b/EthernetSetup.cpp
index 6c081c2..614d5b5 100644
--- a/EthernetSetup.cpp
+++ b/EthernetSetup.cpp
@@ -20,10 +20,13 @@
#include
#include "NetworkDiag.h"
+#include "NetworkSetup.h"
#include "EthernetSetup.h"
byte EthernetSetup::setup()
{
+ INFO(F("Initialize MAC Address ..."));
+ NetworkSetup::genMacAddress();
INFO(F("Initialize Ethernet with DHCP"));
if (Ethernet.begin(mac) == 0)
@@ -61,7 +64,7 @@ byte EthernetSetup::setup()
maxConnections = 8;
}
- INFO(F("Network Protocol: [%s]"), protocol ? "UDP" : "TCP");
+ INFO(F("Network Protocol: [%s]"), protocol ? "UDP" : "TCP");
switch (protocol)
{
case UDPR:
@@ -102,8 +105,9 @@ byte EthernetSetup::setup()
if (connected)
{
ip = Ethernet.localIP();
- INFO(F("Local IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]);
- INFO(F("Listening on port: [%d]"), port);
+ NetworkSetup::printMacAddress(NetworkSetup::mac);
+ INFO(F("Local IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]);
+ INFO(F("Listening on port: [%d]"), port);
dnsip = Ethernet.dnsServerIP();
INFO(F("DNS server IP address: [%d.%d.%d.%d] "), dnsip[0], dnsip[1], dnsip[2], dnsip[3]);
INFO(F("Number of connections: [%d]"), maxConnections);
diff --git a/NetworkInterface.cpp b/NetworkInterface.cpp
index d9dc552..21f0674 100644
--- a/NetworkInterface.cpp
+++ b/NetworkInterface.cpp
@@ -20,6 +20,7 @@
#include
#include "NetworkDiag.h"
+#include "NetworkSetup.h"
#include "NetworkInterface.h"
#include "Transport.h"
#include "EthernetSetup.h"
@@ -76,6 +77,8 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
bool ok = false;
_nLogLevel = 4; // set the log level to ERROR during setup to get proper information
+ NetworkSetup::setDeviceId();
+
INFO(F("[%s] Transport Setup In Progress ..."), transport ? "Ethernet" : "Wifi");
// configure the Transport and get Ethernet/Wifi server up and running
@@ -130,7 +133,7 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
}
INFO(F("[%s] Transport %s ..."), transport ? "Ethernet" : "Wifi", ok ? "OK" : "Failed");
- _nLogLevel = 0; // set loging back to silent;
+ // _nLogLevel = 0; // set loging back to silent;
}
void NetworkInterface::setup(transportType tt, protocolType pt)
diff --git a/NetworkSetup.cpp b/NetworkSetup.cpp
index 0784efc..6203a4f 100644
--- a/NetworkSetup.cpp
+++ b/NetworkSetup.cpp
@@ -18,7 +18,59 @@
*/
#include
+#include "ArduinoUniqueID.h"
#include "NetworkSetup.h"
+#include "NetworkDiag.h"
+
+bool NetworkSetup::deviceIdSet = false;
+bool NetworkSetup::macAddressSet = false;
+char NetworkSetup::_deviceId[MAXDEVICEID] = {0};
+uint8_t NetworkSetup::mac[6] = MAC_ADDRESS; // default MacAddress
+uint8_t NetworkSetup::apWifiMacAddress[6] = MAC_ADDRESS; // default MacAddress
+uint8_t NetworkSetup::stWifiMacAddress[6] = MAC_ADDRESS; // default MacAddress
+
+static void array_to_string(byte array[], unsigned int len, char buffer[])
+{
+ for (unsigned int i = 0; i < len; i++)
+ {
+ byte nib1 = (array[i] >> 4) & 0x0F;
+ byte nib2 = (array[i] >> 0) & 0x0F;
+ buffer[i * 2 + 0] = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA;
+ buffer[i * 2 + 1] = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA;
+ }
+ buffer[len * 2] = '\0';
+}
+
+void NetworkSetup::setDeviceId()
+{
+ array_to_string(UniqueID, UniqueIDsize, _deviceId);
+ DBG(F("Unique device ID: %s\n"), _deviceId);
+ deviceIdSet = true;
+}
+
+void NetworkSetup::printMacAddress(uint8_t a[]) {
+ INFO(F("MAC Address: [%x:%x:%x:%x:%x:%x]"),a[0],a[1],a[2],a[3],a[4],a[5]);
+}
+
+/**
+ * @brief generates Mac Addresses for Ethernet and WiFi
+ *
+ */
+void NetworkSetup::genMacAddress() {
+
+ if (!deviceIdSet) NetworkSetup::setDeviceId();
+ if (!macAddressSet) {
+ for (byte i = 0; i < 6; i++)
+ {
+ mac[i] = UniqueID[i];
+ };
+ }
+ macAddressSet = true;
+}
NetworkSetup::NetworkSetup() {}
-NetworkSetup::~NetworkSetup() {}
\ No newline at end of file
+NetworkSetup::~NetworkSetup() {}
+
+
+ // WiFi.apMacAddress(apWifiMacAddress);
+ // WiFi.macAddress(stWifiMacAddress);
\ No newline at end of file
diff --git a/NetworkSetup.h b/NetworkSetup.h
index 784c610..d7ab986 100644
--- a/NetworkSetup.h
+++ b/NetworkSetup.h
@@ -25,18 +25,36 @@
#include "NetworkConfig.h"
#include "NetworkInterface.h"
+#define MAXDEVICEID 20
+
class NetworkSetup
{
private:
+
+
+ static char _deviceId[MAXDEVICEID];
+ static bool macAddressSet;
+ static bool deviceIdSet;
+
public:
IPAddress dnsip;
IPAddress ip;
- uint8_t mac[6] = MAC_ADDRESS;
+ static uint8_t mac[6]; // Default if not set automatically for EthernetShield
+ static uint8_t apWifiMacAddress[6]; // for the WiFi AP
+ static uint8_t stWifiMacAddress[6]; // for the normal WiFi connection
+
uint8_t maxConnections;
bool connected; // semantics is that the server has successfullt started or not; client connections will be started in the Transport object
protocolType protocol;
uint16_t port = LISTEN_PORT; // Default port
+ static void setDeviceId();
+ char *getDeviceId() {
+ return _deviceId;
+ }
+ static void genMacAddress();
+ static void printMacAddress(uint8_t a[]);
+
NetworkSetup();
~NetworkSetup();
};
diff --git a/WifiSetup.cpp b/WifiSetup.cpp
index 7fdef60..e7e899f 100644
--- a/WifiSetup.cpp
+++ b/WifiSetup.cpp
@@ -23,6 +23,8 @@
#include "NetworkSetup.h"
#include "WifiSetup.h"
+void reverseArray(uint8_t arr[], int start, int end);
+
bool WifiSetup::setup() {
/**
* @todo setup using SoftwareSerial or any other Hardware Serial port on the mega (i.e. 2 or 3);
@@ -47,6 +49,11 @@ bool WifiSetup::setup() {
}
INFO(F("Network Protocol: [%s]"), protocol ? "UDP" : "TCP");
+ INFO(F("Initialize MAC Addresses ... "));
+ WiFi.apMacAddress(apWifiMacAddress);
+ reverseArray(apWifiMacAddress, 0, 5); // the MAc is provided in reverse order ...
+ WiFi.macAddress(stWifiMacAddress);
+ reverseArray(stWifiMacAddress, 0, 5);
// Setup the protocol handler
switch (protocol)
@@ -96,6 +103,9 @@ bool WifiSetup::setup() {
if (connected)
{
ip = WiFi.localIP();
+ NetworkSetup::printMacAddress(apWifiMacAddress);
+ NetworkSetup::printMacAddress(stWifiMacAddress);
+
INFO(F("Local IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]);
INFO(F("Listening on port: [%d]"), port);
dnsip = WiFi.dnsServer1();
@@ -107,6 +117,18 @@ bool WifiSetup::setup() {
};
+void reverseArray(uint8_t arr[], int start, int end)
+{
+ while (start < end)
+ {
+ uint8_t temp = arr[start];
+ arr[start] = arr[end];
+ arr[end] = temp;
+ start++;
+ end--;
+ }
+}
+
WifiSetup::WifiSetup() {}
WifiSetup::WifiSetup(uint16_t p, protocolType pt ) { port = p; protocol = pt; }
WifiSetup::~WifiSetup() {}
\ No newline at end of file