diff --git a/EasyLoRaWANGateway/_utils.ino b/EasyLoRaWANGateway/_utils.ino deleted file mode 100644 index 158584f..0000000 --- a/EasyLoRaWANGateway/_utils.ino +++ /dev/null @@ -1,564 +0,0 @@ -// 1-channel LoRa Gateway for ESP8266 and ESP32 -// Copyright (c) 2016-2020 Maarten Westenberg version for ESP8266 -// -// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway -// and many others. -// -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the MIT License -// which accompanies this distribution, and is available at -// https://opensource.org/licenses/mit-license.php -// -// NO WARRANTY OF ANY KIND IS PROVIDED -// -// Author: Maarten Westenberg (mw12554@hotmail.com) -// -// This file contains the utilities for time and other functions -// ======================================================================================== - - - -// ==================== STRING STRING STRING ============================================== - -// -------------------------------------------------------------------------------- -// PRINT INT -// The function printInt prints a number with Thousands seperator -// Paraneters: -// i: Integer containing Microseconds -// response: String & value containig the converted number -// Retur: -// -// -------------------------------------------------------------------------------- -void printInt (uint32_t i, String & response) -{ - response+=(String(i/1000000) + "." + String(i%1000000)); -} - -// -------------------------------------------------------------------------------- -// PRINT Dwn -// IN a uniform way, this function prints the timstamp, the current time and the -// time the function must wait to execute. It will print all Downstream data -// -------------------------------------------------------------------------------- -void printDwn(struct LoraDown *LoraDown, String & response) -{ - uint32_t i= LoraDown->tmst; - uint32_t m= micros(); - - response += "micr="; printInt(m, response); - response += ", tmst="; printInt(i, response); - - response += ", wait="; - if (i>m) { - response += String(i-m); - } - else { - response += "("; - response += String(m-i); - response += ")"; - } - - response += ", SF=" +String(LoraDown->sfTx); - response += ", Freq=" +String(LoraDown->freq); - - response += ", a="; - uint8_t DevAddr [4]; - DevAddr[0] = LoraDown->payLoad[4]; - DevAddr[1] = LoraDown->payLoad[3]; - DevAddr[2] = LoraDown->payLoad[2]; - DevAddr[3] = LoraDown->payLoad[1]; - printHex((IPAddress)DevAddr, ':', response); - - yield(); - return; -} - - -// -------------------------------------------------------------------------------- -// PRINT IP -// Output the 4-byte IP address for easy printing. -// As this function is also used by _otaServer.ino do not put in #define -// Parameters: -// ipa: The Ip Address (input) -// sep: Separator character (input) -// response: The response string (output) -// Return: -// -// -------------------------------------------------------------------------------- -void printIP(IPAddress ipa, const char sep, String & response) -{ - response+=(String)ipa[0]; response+=sep; - response+=(String)ipa[1]; response+=sep; - response+=(String)ipa[2]; response+=sep; - response+=(String)ipa[3]; -} - -// ---------------------------------------------------------------------------------------- -// Fill a HEXadecimal String from a 4-byte char array (uint32_t) -// -// ---------------------------------------------------------------------------------------- -void printHex(uint32_t hexa, const char sep, String & response) -{ -# if _MONITOR>=1 - if ((debug>=0) && (hexa==0)) { - mPrint("printHex:: hexa amount to convert is 0"); - } -# endif - - uint8_t * h = (uint8_t *)(& hexa); - - if (h[0]<016) response+='0'; response += String(h[0], HEX); response+=sep; - if (h[1]<016) response+='0'; response += String(h[1], HEX); response+=sep; - if (h[2]<016) response+='0'; response += String(h[2], HEX); response+=sep; - if (h[3]<016) response+='0'; response += String(h[3], HEX); response+=sep; -} - -// ---------------------------------------------------------------------------- -// Print uint8_t values in HEX with leading 0 when necessary -// ---------------------------------------------------------------------------- -void printHexDigit(uint8_t digit, String & response) -{ - // utility function for printing Hex Values with leading 0 - if(digit < 0x10) - response += '0'; - response += String(digit,HEX); - -} - -// ========================= MONITOR FUNCTIONS ============================================ -// Monitor functions -// These functions write to the Monitor and print the monitor. - - -// ---------------------------------------------------------------------------------------- -// Print to the monitor console. -// This function is used all over the gateway code as a substitute for USB debug code. -// It allows webserver users to view printed/debugging code. -// With initMonitor() we init the index iMoni=0; -// -// Parameters: -// txt: The text to be printed. -// return: -// -// ---------------------------------------------------------------------------------------- -void mPrint(String txt) -{ -# if _MONITOR>=1 - time_t tt = now(); - - monitor[iMoni].txt = ""; - stringTime(tt, monitor[iMoni].txt); - - monitor[iMoni].txt += "- " + String(txt); - - // Use the circular buffer to increment the index - -# if _DUSB>=1 - if (gwayConfig.dusbStat>=1) { - Serial.println(monitor[iMoni].txt); // Copy to serial when configured - } -# endif //_DUSB - - iMoni = (iMoni+1) % _MAXMONITOR ; // And goto 0 when skipping over _MAXMONITOR - -# endif //_MONITOR - - return; -} - - -// ---------------------------------------------------------------------------- -// mStat (Monitor-Statistics) -// Print the statistics on Serial (USB) port and/or Monitor -// Depending on setting of _DUSB and _MONITOR. -// Note: This function does not initialise the response var, will only append. -// Parameters: -// Interrupt: 8-bit -// Response: String -// Return: -// 1: If successful -// 0: No Success -// ---------------------------------------------------------------------------- -int mStat(uint8_t intr, String & response) -{ -#if _MONITOR>=1 - - if (debug>=0) { - - response += "I="; - - if (intr & IRQ_LORA_RXTOUT_MASK) response += "RXTOUT "; // 0x80 - if (intr & IRQ_LORA_RXDONE_MASK) response += "RXDONE "; // 0x40 - if (intr & IRQ_LORA_CRCERR_MASK) response += "CRCERR "; // 0x20 - if (intr & IRQ_LORA_HEADER_MASK) response += "HEADER "; // 0x10 - if (intr & IRQ_LORA_TXDONE_MASK) response += "TXDONE "; // 0x08 - if (intr & IRQ_LORA_CDDONE_MASK) response += "CDDONE "; // 0x04 - if (intr & IRQ_LORA_FHSSCH_MASK) response += "FHSSCH "; // 0x02 - if (intr & IRQ_LORA_CDDETD_MASK) response += "CDDETD "; // 0x01 - - if (intr == 0x00) response += " -- "; - - response += ", F=" + String(gwayConfig.ch); - - response += ", SF=" + String(sf); - - response += ", E=" + String(_event); - - response += ", S="; - switch (_state) { - case S_INIT: - response += "INIT "; - break; - case S_SCAN: - response += "SCAN "; - break; - case S_CAD: - response += "CAD "; - break; - case S_RX: - response += "RX "; - break; - case S_TX: - response += "TX "; - break; - case S_TXDONE: - response += "TXDONE"; - break; - default: - response += " -- "; - } - response += ", eT="; - response += String( micros() - eventTime ); - - response += ", dT="; - response += String( micros() - doneTime ); - } -#endif //_MONITOR - return(1); -} - - - - -// ============== NUMBER FUNCTIONS ============================================ - - -// ---------------------------------------------------------------------------- -// Convert a float to string for printing -// Parameters: -// f is float value to convert -// p is precision in decimal digits -// val is character array for results -// ---------------------------------------------------------------------------- -void ftoa(float f, char *val, int p) -{ - int j=1; - int ival, fval; - char b[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - for (int i=0; i< p; i++) { j= j*10; } - - ival = (int) f; // Make integer part - fval = (int) ((f- ival)*j); // Make fraction. Has same sign as integer part - if (fval<0) fval = -fval; // So if it is negative make fraction positive again. - // sprintf does NOT fit in memory - if ((f<0) && (ival == 0)) strcat(val, "-"); - strcat(val,itoa(ival,b,10)); // Copy integer part first, base 10, null terminated - strcat(val,"."); // Copy decimal point - - itoa(fval,b,10); // Copy fraction part base 10 - for (unsigned int i=0; i<(p-strlen(b)); i++) { - strcat(val,"0"); // first number of 0 of faction? - } - - // Fraction can be anything from 0 to 10^p , so can have less digits - strcat(val,b); -} - - - -// ============== SERIAL SERIAL SERIAL ======================================== - - -// ---------------------------------------------------------------------------- -// Print leading '0' digits for hours(0) and second(0) when -// printing values less than 10 -// ---------------------------------------------------------------------------- -void printDigits(uint32_t digits) -{ - // utility function for digital clock display: prints leading 0 - if(digits < 10) - Serial.print(F("0")); - Serial.print(digits); -} - - -// ============================================================================ -// NTP TIME functions -// These helper function deal with the Network Time Protool(NTP) functions. -// ============================================================================ - - - -// ---------------------------------------------------------------------------------------- -// stringTime -// Print the time t into the String reponse. t is of type time_t in seconds. -// Only when RTC is present we print real time values -// t contains number of seconds since system started that the event happened. -// So a value of 100 would mean that the event took place 1 minute and 40 seconds ago -// ---------------------------------------------------------------------------------------- -static void stringTime(time_t t, String & response) -{ - - if (t==0) { response += "--"; return; } - - // now() gives seconds since 1970 - // as millis() does rotate every 50 days - // So we need another timing parameter - time_t eTime = t; - - // Rest is standard - byte _hour = hour(eTime); - byte _minute = minute(eTime); - byte _second = second(eTime); - - byte _month = month(eTime); - byte _day = day(eTime); - - switch(weekday(eTime)) { - case 1: response += "Sun "; break; - case 2: response += "Mon "; break; - case 3: response += "Tue "; break; - case 4: response += "Wed "; break; - case 5: response += "Thu "; break; - case 6: response += "Fri "; break; - case 7: response += "Sat "; break; - } - if (_day < 10) response += "0"; response += String(_day) + "-"; - if (_month < 10) response += "0"; response += String(_month) + "-"; - response += String(year(eTime)) + " "; - - if (_hour < 10) response += "0"; response += String(_hour) + ":"; - if (_minute < 10) response += "0"; response += String(_minute) + ":"; - if (_second < 10) response += "0"; response += String(_second); -} - -// ---------------------------------------------------------------------------- -// Send the time request packet to the NTP server. -// -// ---------------------------------------------------------------------------- -int sendNtpRequest(IPAddress timeServerIP) -{ - const int NTP_PACKET_SIZE = 48; // Fixed size of NTP record - byte packetBuffer[NTP_PACKET_SIZE]; - - memset(packetBuffer, 0, NTP_PACKET_SIZE); // Zero the buffer. - - packetBuffer[0] = 0b11100011; // LI, Version, Mode - packetBuffer[1] = 0; // Stratum, or type of clock - packetBuffer[2] = 6; // Polling Interval - packetBuffer[3] = 0xEC; // Peer Clock Precision - // 8 bytes of zero for Root Delay & Root Dispersion - packetBuffer[12] = 49; - packetBuffer[13] = 0x4E; - packetBuffer[14] = 49; - packetBuffer[15] = 52; - - - if (!sendUdp( (IPAddress) timeServerIP, (int) 123, packetBuffer, NTP_PACKET_SIZE)) { - gwayConfig.ntpErr++; - gwayConfig.ntpErrTime = now(); - return(0); - } - return(1); - -} // sendNtpRequest() - - -// ---------------------------------------------------------------------------- -// Get the NTP time from one of the time servers -// Note: As this function is called from SyncInterval in the background -// make sure we have no blocking calls in this function -// parameters: -// t: the resulting time_t -// return: -// 0: when fail -// >=1: when success -// ---------------------------------------------------------------------------- -int getNtpTime(time_t *t) -{ - gwayConfig.ntps++; - - if (!sendNtpRequest(ntpServer)) // Send the request for new time - { -# if _MONITOR>=1 - if (debug>=0) { - mPrint("utils:: ERROR getNtpTime: sendNtpRequest failed"); - } -# endif //_MONITOR - return(0); - } - - const int NTP_PACKET_SIZE = 48; // Fixed size of NTP record - byte packetBuffer[NTP_PACKET_SIZE]; - memset(packetBuffer, 0, NTP_PACKET_SIZE); // Set buffer contents to zero - - uint32_t beginWait = millis(); - delay(10); - while (millis() - beginWait < 1500) // Wait for 1500 millisecs - { - int size = Udp.parsePacket(); - if ( size >= NTP_PACKET_SIZE ) { - - if (Udp.read(packetBuffer, NTP_PACKET_SIZE) < NTP_PACKET_SIZE) { -# if _MONITOR>=1 - if (debug>=0) { - mPrint("getNtpTime:: ERROR packetsize too low"); - } -# endif //_MONITOR - break; // Error, or should we use continue - } - else { - // Extract seconds portion. - uint32_t secs; - secs = packetBuffer[40] << 24; - secs |= packetBuffer[41] << 16; - secs |= packetBuffer[42] << 8; - secs |= packetBuffer[43]; - - // in NL UTC is 1 TimeZone correction when no daylight saving time - *t = (time_t)(secs - 2208988800UL + NTP_TIMEZONES * SECS_IN_HOUR); - Udp.flush(); - return(1); - } - Udp.flush(); - } - delay(100); // Wait 100 millisecs, allow kernel to act when necessary - } - - Udp.flush(); - - // If we are here, we could not read the time from internet - // So increase the counter - gwayConfig.ntpErr++; - gwayConfig.ntpErrTime = now(); - -# if _MONITOR>=1 - if ((debug>=3) && (pdebug & P_MAIN)) { - mPrint("getNtpTime:: WARNING read time failed"); // but we return 0 to indicate this to caller - } -# endif //_MONITOR - - return(0); // return 0 if unable to get the time -} //getNtpTime - - -// ---------------------------------------------------------------------------- -// Set up regular synchronization of NTP server and the local time. -// ---------------------------------------------------------------------------- -#if NTP_INTR==1 -void setupTime() -{ - time_t t; - getNtpTime(&t); - setSyncProvider(t); - setSyncInterval(_NTP_INTERVAL); -} -#endif //NTP_INTR - - - - -// ---------------------------------------------------------------------------- -// SerialName(id, response) -// Check whether for address a (4 bytes in uint32_t) there is a -// Trusted Node name. It will return the index of that name in nodex struct. -// Otherwise it returns -1. -// This function only works if _TRUSTED_NODES is set. -// ---------------------------------------------------------------------------- - -int SerialName(uint32_t a, String & response) -{ -#if _TRUSTED_NODES>=1 - uint8_t * in = (uint8_t *)(& a); - uint32_t id = ((in[0]<<24) | (in[1]<<16) | (in[2]<<8) | in[3]); - - for (unsigned int i=0; i< (sizeof(nodes)/sizeof(nodex)); i++) { - - if (id == nodes[i].id) { -# if _MONITOR>=1 - if ((debug>=3) && (pdebug & P_MAIN )) { - mPrint("SerialName:: i="+String(i)+", Name="+String(nodes[i].nm)+". for node=0x"+String(nodes[i].id,HEX)); - } -# endif //_MONITOR - - response += nodes[i].nm; - return(i); - } - } -#endif // _TRUSTED_NODES - - return(-1); // If no success OR is TRUSTED NODES not defined -} //SerialName - - -#if _LOCALSERVER==1 -// ---------------------------------------------------------------------------- -// inDecodes(id) -// Find the id in Decodes array, and return the index of the item -// Parameters: -// id: The first field in the array (normally DevAddr id). Must be char[4] -// Returns: -// The index of the ID in the Array. Returns -1 if not found -// ---------------------------------------------------------------------------- -int inDecodes(char * id) { - - uint32_t ident = ((id[3]<<24) | (id[2]<<16) | (id[1]<<8) | id[0]); - - for (unsigned int i=0; i< (sizeof(decodes)/sizeof(codex)); i++) { - if (ident == decodes[i].id) { - return(i); - } - } - return(-1); -} -#endif - - - -// ============================= GENERAL SKETCH =============================== - -// ---------------------------------------------------------------------------- -// DIE is not used actively in the source code apart from resolveHost(). -// It is replaced by a Serial.print command so we know that we have a problem -// somewhere. -// There are at least 3 other ways to restart the ESP. Pick one if you want. -// ---------------------------------------------------------------------------- -void die(String s) -{ -# if _MONITOR>=1 - mPrint(s); -# endif //_MONITOR - -# if _DUSB>=1 - Serial.println(s); - if (debug>=2) Serial.flush(); -# endif //_DUSB - - delay(50); - abort(); // Within a second -} - - -// ---------------------------------------------------------------------------- -// gway_failed is a function called by ASSERT in configGway.h -// -// ---------------------------------------------------------------------------- -void gway_failed(const char *file, uint16_t line) { -#if _MONITOR>=1 - String response = "Program failed in file: "; - response += String(file); - response += ", line: "; - response += String(line); - mPrint(response); -#endif //_MONITOR -}