// hd44780 library see https://github.com/duinoWitchery/hd44780
// thehd44780 library is available through the IDE library manager
#include <Wire.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
#include <WiFi.h>
#include <SafeString.h>
//char* ssid = "FRITZ!Box 7490";
//char* password = "";
char* ssid = "Wokwi-GUEST";
char* password = "";
IPAddress remoteIP(192, 168, 178, 255); // receiver-IP
IPAddress broadCastIP(192, 168, 178, 255); // receiver-IP
//IPAddress remoteIP (172, 20, 100, 87); // receiver-IP// 172.20.100.87
//unsigned int remotePort = 4210; // receiver port to listen on must match the portnumber the receiver is listening to
int remotePort = 4210; // receiver port to listen on must match the portnumber the receiver is listening to
IPAddress local_IP;
WiFiUDP Udp;
#define HelloMsg "HalloRaspi"
#define UDP_RcvBufLen 256
char UDP_RcvBuffer[UDP_RcvBufLen];
boolean IP_FromTerra;
//const char* ntpServer = "134.60.111.110";
const char* ntpServer = "2.de.pool.ntp.org";
const long gmtOffset_sec = 0;
const int daylightOffset_sec = 7200;
#include <time.h> // time() ctime()
time_t now; // this is the epoch
tm myTimeInfo; // the structure tm holds time information in a more convient way
unsigned long TestTimer;
unsigned long UDP_SendTimer;
unsigned long UDP_BroadcastTimer;
int myCounter = 0;
int HeaderNr = 0;
#define MaxMsgLength 1024
createSafeString(UDP_Msg_SS, MaxMsgLength);
#define MaxHeaderLength 64
createSafeString(Header_SS, MaxHeaderLength);
#define MaxTimeStampLength 32
createSafeString(TimeStamp_SS, MaxHeaderLength);
createSafeString(IP_Adress_SS, MaxHeaderLength);
createSafeString(StatusMsg_SS, MaxMsgLength);
createSafeString(TerraMsg_SS, MaxMsgLength);
char HeaderDelimiter = '$'; // must match the delimiter defined in the python-code
char Delimiter = '$';
const byte OnBoard_LED = 2;
unsigned long BlinkTime = 500;
// if there should be an additional I2C-devices on the I2C-Bus
// which has a lower I2C-adress it might happen that this other devices I2C-adress
// will be chosen as the I2C-adress of the LCD
// if this happends add the I2C-adress to the constructor of the HD44780
// example instead of writing hd44780_I2Cexp lcd;
// add the I2C-adress hd44780_I2Cexp (0x27);
hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
void updateLCD() {
static unsigned long lcdTimer = 0;
if ( TimePeriodIsOver(lcdTimer, 500) ) { // check if more than 500 milliseconds have passed by
// if 500 milliseconds HAVE passed by
lcd.setCursor(8, 1);
lcd.print(" "); // overwrite old data
lcd.setCursor(8, 1); // reset the cursor
lcd.print(millis());
}
}
void PrintFileNameDateTime() {
Serial.println(F("Code running comes from file "));
Serial.println(F(__FILE__));
Serial.print(F(" compiled "));
Serial.print(F(__DATE__));
Serial.print(F(" "));
Serial.println(F(__TIME__));
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long & startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if (TimePeriodIsOver(MyBlinkTimer, BlinkPeriod)) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin));
}
}
void showTime() {
time(&now); // read the current time
localtime_r(&now, &myTimeInfo); // update the structure tm with the current time
Serial.print(F("year:"));
Serial.print(myTimeInfo.tm_year + 1900); // years since 1900
Serial.print(F("\tmonth:"));
Serial.print(myTimeInfo.tm_mon + 1); // January = 0 (!)
Serial.print(F("\tday:"));
Serial.print(myTimeInfo.tm_mday); // day of month
Serial.print(F("\thour:"));
Serial.print(myTimeInfo.tm_hour); // hours since midnight 0-23
Serial.print(F("\tmin:"));
Serial.print(myTimeInfo.tm_min); // minutes after the hour 0-59
Serial.print(F("\tsec:"));
Serial.print(myTimeInfo.tm_sec); // seconds after the minute 0-61*
Serial.print(F("\twday"));
Serial.print(myTimeInfo.tm_wday); // days since Sunday 0-6
if (myTimeInfo.tm_isdst == 1) // Daylight Saving Time flag
Serial.print(F("\tDST"));
else
Serial.print(F("\tstandard"));
Serial.println();
}
// my personal naming-convention parameter of functions start with prefix "p_"
void StoreTimeStampIntoSS(SafeString& p_RefToSS) {
time(&now); // read the current time
localtime_r(&now, &myTimeInfo); // update the structure tm with the current time
//p_RefToSS = " ";
p_RefToSS = myTimeInfo.tm_year + 1900;
p_RefToSS += ".";
if (myTimeInfo.tm_mon < 10) {
p_RefToSS += "0"; // leading zero
}
p_RefToSS += myTimeInfo.tm_mon + 1;
p_RefToSS += ".";
if (myTimeInfo.tm_mday < 10) {
p_RefToSS += "0"; // leading zero
}
p_RefToSS += myTimeInfo.tm_mday;
p_RefToSS += "; ";
if (myTimeInfo.tm_hour < 10) {
p_RefToSS += "0"; // leading zero
}
p_RefToSS += myTimeInfo.tm_hour;
p_RefToSS += ":";
if (myTimeInfo.tm_min < 10) {
p_RefToSS += "0"; // leading zero
}
p_RefToSS += myTimeInfo.tm_min;
p_RefToSS += ":";
if (myTimeInfo.tm_sec < 10) {
p_RefToSS += "0"; // leading zero
}
p_RefToSS += myTimeInfo.tm_sec;
p_RefToSS += " ; ";
}
void connectToWifi() {
Serial.print(F("Connecting to "));
Serial.println(ssid);
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
BlinkHeartBeatLED(OnBoard_LED, 333);
delay(332);
Serial.print(".");
}
Serial.print(F("\n connected."));
Serial.println(WiFi.localIP());
//remoteIP = WiFi.localIP();
//remoteIP[3] = 255;
Serial.print(F("remote-IP"));
Serial.println(remoteIP);
}
void synchroniseWith_NTP_Time() {
unsigned long Count = 0;
Serial.print(F("configTime uses ntpServer "));
Serial.println(ntpServer);
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Serial.print(F("synchronising time"));
while (myTimeInfo.tm_year + 1900 < 2000) {
time(&now); // read the current time
localtime_r(&now, &myTimeInfo);
BlinkHeartBeatLED(OnBoard_LED, 250);
delay(100);
Serial.print(".");
Count++;
if (Count > 100) {
break;
}
}
Serial.print(F("\n time synchronsized \n"));
showTime();
}
void PrintMsg() {
Serial.print(F("UDP_Msg_SS #"));
;
Serial.print(UDP_Msg_SS);
Serial.println("#");
}
void ipToSafeString(SafeString& p_RefToSS, IPAddress ip) {
p_RefToSS = ip[0];
p_RefToSS += ".";
p_RefToSS += ip[1];
p_RefToSS += ".";
p_RefToSS += ip[2];
p_RefToSS += ".";
p_RefToSS += ip[3];
}
void SendUDP_Msg() {
Serial.print(F("Send Message to #"));
Serial.print(remoteIP);
Serial.print(F(":"));
Serial.println(remotePort);
UDP_Msg_SS = Header_SS;
UDP_Msg_SS += HeaderDelimiter;
StoreTimeStampIntoSS(TimeStamp_SS);
UDP_Msg_SS += TimeStamp_SS;
UDP_Msg_SS += Delimiter;
UDP_Msg_SS += StatusMsg_SS;
UDP_Msg_SS += Delimiter;
UDP_Msg_SS += myCounter++;
Serial.print(F("Send UDP_Msg #"));
Serial.print(UDP_Msg_SS);
Serial.println("#");
Udp.beginPacket(remoteIP, remotePort);
Udp.write((const uint8_t*)UDP_Msg_SS.c_str(), UDP_Msg_SS.length());
Udp.endPacket();
}
void UDP_receive() {
int packetSize;
int len;
packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Empfangen ");
Serial.print(packetSize);
Serial.print(" von IP ");
Serial.print(Udp.remoteIP());
Serial.print(" Port ");
Serial.println(Udp.remotePort());
len = Udp.read(UDP_RcvBuffer, UDP_RcvBufLen);
//Udp.read(UDP_RcvBuffer, UDP_RcvBufLen);
Serial.print("rcvd #");
Serial.print(UDP_RcvBuffer);
Serial.println("#");
int i = 0;
TerraMsg_SS = "";
while (i < len) {
TerraMsg_SS += UDP_RcvBuffer[i];
i++;
if (i >= MaxMsgLength) {
break;
}
}
Serial.println(TerraMsg_SS);
if (TerraMsg_SS.compareTo("IbinDerRaspi") == 0 ) {
Serial.println("TerraX antwortet");
remoteIP = Udp.remoteIP();
IP_FromTerra = true;
}
}
}
void setup() {
Serial.begin(115200);
Serial.println(F("\n Setup-Start \n"));
PrintFileNameDateTime();
lcd.begin(LCD_COLS, LCD_ROWS);
lcd.clear();
lcd.print("Hello World");
lcd.setCursor(0, 1);
lcd.print("Millis ");
connectToWifi();
synchroniseWith_NTP_Time();
Header_SS = "ESP32";
StatusMsg_SS = "Status charging started at 15:17";
remoteIP = broadCastIP;
IP_FromTerra = false;
Header_SS = HelloMsg;
}
void loop() {
updateLCD();
if (TimePeriodIsOver(UDP_SendTimer, 10000)) {
if (IP_FromTerra) {
Header_SS = "Status";
SendUDP_Msg();
}
if (!IP_FromTerra) {
Serial.println("broadCasting Hello");
remoteIP = broadCastIP;
Header_SS = HelloMsg;
SendUDP_Msg();
}
UDP_receive();
}
}