2023-08-22 12:23:47 -05:00
/*********
Rui Santos
Complete project details at https : //RandomNerdTutorials.com/esp32-esp8266-input-data-html-form/
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files .
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software .
* * * * * * * * */
// include wifi password
# include "config.h"
# include <Arduino.h>
# include <WiFi.h>
# include <AsyncTCP.h>
# include <SPIFFS.h>
# include <Preferences.h>
2023-09-13 20:24:57 -05:00
# include "morse.h"
2023-09-02 18:45:50 -05:00
# include <Adafruit_BusIO_Register.h> // for DS3231
# include <RTClib.h> // for DS3231
2023-09-05 20:41:55 -05:00
# include <string>
2023-08-22 12:23:47 -05:00
// download zip from https://github.com/me-no-dev/ESPAsyncWebServer and install.
# include <ESPAsyncWebServer.h>
AsyncWebServer server ( 80 ) ;
2023-09-13 21:06:16 -05:00
// Assign output variables to GPIO pins
2023-09-15 19:58:46 -05:00
//LED_BUILTIN for ESP32 onboard LED, 32 for transmitter keyer
const int keyer = 32 ;
2023-09-13 21:06:16 -05:00
const int blinker = LED_BUILTIN ;
2023-09-02 22:11:51 -05:00
RTC_DS3231 rtc ; // set up RTC
2023-09-08 10:39:24 -05:00
const int alarmPin = 4 ; // pin to monitor for RTC alarms
2023-09-02 18:45:50 -05:00
2023-09-25 21:53:20 -05:00
// Network options: "0" for existing netowrk, "1" to be an access point
const int network = 1 ;
2023-09-25 21:36:37 -05:00
// Connect to existing network
2023-08-22 12:23:47 -05:00
// Read from config.h
2023-09-26 20:57:41 -05:00
//const char* ssid = WIFI_SSID;
//const char* password = WIFI_PASSWORD;
2023-09-25 21:36:37 -05:00
// Create a new access point
2023-09-25 21:47:48 -05:00
// Replace with your desired network credentials
const char * ssid_ap = " vulpes " ;
const char * password_ap = NULL ; //"123456789"; //NULL is empty
2023-09-25 21:36:37 -05:00
IPAddress local_ip ( 192 , 168 , 0 , 1 ) ;
IPAddress gateway ( 192 , 168 , 0 , 1 ) ;
IPAddress subnet ( 255 , 255 , 255 , 0 ) ;
2023-08-22 12:23:47 -05:00
2023-08-31 20:41:24 -05:00
const char * PARAM_SEND = " inputSend " ;
2023-08-31 21:35:49 -05:00
const char * PARAM_WPM = " inputWPM " ;
const char * PARAM_MSG = " inputMsg " ;
2023-09-16 09:51:39 -05:00
const char * PARAM_CMSG = " inputCustomMsg " ;
2023-08-22 12:23:47 -05:00
const char * PARAM_FLOAT = " inputFloat " ;
2023-09-02 18:45:50 -05:00
const char * PARAM_TIME = " inputTimeUnix " ;
2023-09-04 21:53:09 -05:00
const char * PARAM_START = " inputStartTimeUnix " ;
2023-09-05 20:41:55 -05:00
const char * PARAM_RUNNING = " programRunning " ;
2023-09-10 12:35:02 -05:00
const char * PARAM_STEPLENGTH = " inputStepLength " ;
const char * PARAM_CYCLEID = " inputCycleID " ;
const char * PARAM_NTRANS = " inputNtransmitters " ;
2023-09-26 20:57:41 -05:00
const char * PARAM_NETWORK = " inputNetwork " ;
const char * PARAM_SSID = " inputSSID " ;
const char * PARAM_PASSWORD = " inputPassword " ;
2023-08-22 12:23:47 -05:00
2023-08-31 09:10:30 -05:00
// Global variables
2023-08-31 20:41:24 -05:00
int yourInputSend ;
2023-08-31 21:35:49 -05:00
int yourInputWPM ;
2023-09-01 10:01:49 -05:00
int yourInputMsg ;
int yourInputMsg_old ; // to save previous state and check changes
2023-09-16 09:51:39 -05:00
String yourInputCustomMsg ;
2023-08-31 09:10:30 -05:00
float yourInputFloat ;
2023-09-02 22:11:51 -05:00
uint32_t yourInputTime ; //to keep time
2023-09-04 21:53:09 -05:00
uint32_t yourInputStartTimeUnix ;
2023-09-09 16:01:41 -05:00
bool startProgram ;
bool programRunning ;
2023-09-10 12:35:02 -05:00
int yourInputStepLength ;
int yourInputCycleID ;
int yourInputNtransmitters ;
2023-09-26 20:57:41 -05:00
int yourInputNetwork ;
String yourInputSSID ;
String yourInputPassword ;
2023-09-14 12:44:10 -05:00
long start_millis = 0 ;
long stop_millis = 0 ;
2023-09-14 21:02:28 -05:00
long pause_until_millis = 0 ;
2023-08-31 09:10:30 -05:00
2023-09-16 09:51:39 -05:00
// HTML web page to handle input fields
2023-08-22 12:23:47 -05:00
const char index_html [ ] PROGMEM = R " rawliteral(
< ! DOCTYPE HTML > < html > < head >
2023-09-06 20:14:16 -05:00
< link rel = " icon " href = " data:, " >
2023-08-22 12:23:47 -05:00
< title > ESP Input Form < / title >
< meta name = " viewport " content = " width=device-width, initial-scale=1 " >
2023-09-06 18:02:07 -05:00
< script type = " text/javascript " >
2023-09-06 21:21:05 -05:00
// Utility from https://webreflection.medium.com/using-the-input-datetime-local-9503e7efdce
Date . prototype . toDatetimeLocal = function toDatetimeLocal ( ) {
var
date = this ,
ten = function ( i ) {
return ( i < 10 ? ' 0 ' : ' ' ) + i ;
} ,
YYYY = date . getFullYear ( ) ,
MM = ten ( date . getMonth ( ) + 1 ) ,
DD = ten ( date . getDate ( ) ) ,
HH = ten ( date . getHours ( ) ) ,
II = ten ( date . getMinutes ( ) ) ,
SS = ten ( date . getSeconds ( ) )
;
return YYYY + ' - ' + MM + ' - ' + DD + ' T ' +
HH + ' : ' + II + ' : ' + SS ;
}
2023-09-06 21:52:04 -05:00
// Submit timestamps as unix seconds when form is submitted
2023-09-02 20:02:59 -05:00
var putDate = function ( form ) {
2023-09-06 21:21:05 -05:00
form . inputTimeUnix . value = Math . floor ( Date . now ( ) / 1000 ) ; // - new Date().getTimezoneOffset()*60;
2023-09-06 20:14:16 -05:00
form . inputStartTimeUnix . value = ( ( Date . parse ( js_start_time_unix_entry . value ) ) / 1000 ) ;
//document.getElementById("js_start_time_unix").value = ((Date.parse(js_start_time_unix_entry.value))/1000);
2023-09-06 18:02:07 -05:00
}
2023-09-06 21:52:04 -05:00
// Fill in page values
2023-09-05 11:08:01 -05:00
window . onload = function ( ) {
2023-09-06 18:08:36 -05:00
s = % inputStartTimeUnix % ;
2023-09-05 16:55:42 -05:00
current_start = new Date ( s * 1000 ) ;
2023-09-06 21:21:05 -05:00
document . getElementById ( ' current - start ' ) . innerHTML = current_start . toLocaleString ( ) ;
// Show the local time as a string
local_time_unix = new Date ( ) . toLocaleString ( ) ; //toUTCString();
2023-09-06 16:57:57 -05:00
document . getElementById ( ' local - time - unix ' ) . innerHTML = local_time_unix . toString ( ) ;
2023-09-06 21:52:04 -05:00
// Fill in the start time field as local time
2023-09-06 21:21:05 -05:00
document . getElementById ( ' js_start_time_unix_entry ' ) . value = current_start . toDatetimeLocal ( ) ;
2023-09-06 21:52:04 -05:00
// Fill in the other form fields
document . getElementById ( " send-program " ) . value = % inputSend % ;
document . getElementById ( " message " ) . value = % inputMsg % ;
2023-09-26 20:57:41 -05:00
document . getElementById ( " network " ) . value = % inputNetwork % ;
2023-09-05 11:08:01 -05:00
}
2023-09-05 16:55:42 -05:00
2023-08-22 12:23:47 -05:00
< / script > < / head > < body >
2023-09-10 12:35:02 -05:00
< h1 > Vulpes Radio Orienteering Controller < / h1 >
2023-09-27 20:12:38 -05:00
< p > Local time : < b > < span id = local - time - unix > < / span > < / b > . If this is incorrect , your browser is not providing the correct time
( < a href = " https://support.mozilla.org/en-US/questions/1297208 " > Firefox example < / a > ) . < / p >
2023-09-05 21:11:31 -05:00
2023-09-06 21:36:10 -05:00
< form action = " /get " onsubmit = " putDate(this); " accept - charset = utf - 8 >
2023-09-10 12:35:02 -05:00
< h2 > General Settings < / h2 >
< p > Sending program :
2023-08-31 20:41:24 -05:00
< select name = " inputSend " id = " send-program " >
2023-09-06 21:52:04 -05:00
< option value = " 0 " > 0 - Off < / option >
2023-09-01 14:15:54 -05:00
< option value = " 1 " > 1 - Continuous < / option >
2023-09-08 15:00:48 -05:00
< option value = " 2 " > 2 - Cycle < / option >
2023-08-31 11:52:11 -05:00
< / select > < br >
2023-08-31 21:35:49 -05:00
2023-09-10 12:35:02 -05:00
Message :
2023-08-31 21:35:49 -05:00
< select name = " inputMsg " id = " message " >
2023-09-16 09:51:39 -05:00
< option value = " 0 " > 0 - Custom Message < / option >
2023-09-01 14:15:54 -05:00
< option value = " 1 " > 1 - MOE < / option >
< option value = " 2 " > 2 - MOI < / option >
< option value = " 3 " > 3 - MOS < / option >
< option value = " 4 " > 4 - MOH < / option >
< option value = " 5 " > 5 - MO5 < / option >
2023-09-15 21:44:19 -05:00
< / select > < br >
2023-09-16 09:51:39 -05:00
Custom message : < input type = " text " name = " inputCustomMsg " value = " %inputCustomMsg% " > < br >
2023-09-15 21:44:19 -05:00
Speed : < input type = " number " name = " inputWPM " value = % inputWPM % > WPM
< / p >
2023-09-05 20:41:55 -05:00
2023-09-10 12:35:02 -05:00
< h2 > Cycle Settings < / h2 >
2023-09-11 21:09:27 -05:00
< p > Only applies when < em > Sending Program < / em > is set to " 2 - Cycle " . You cannot set a cycle start date more than a month in advance . < / p >
2023-09-08 15:00:48 -05:00
< p > Cycle start time < input type = " datetime-local " id = " js_start_time_unix_entry " / > < br >
2023-09-11 21:09:27 -05:00
Current value : < b > < span id = current - start > < / span > < / b >
2023-09-05 20:41:55 -05:00
< ! - - JS converts the entered start time to a unix timestamp , and copies that value
to this hidden field so the user doesn ' t have to see it . - - >
< input type = " hidden " name = " inputStartTimeUnix " id = " js_start_time_unix " / > < / p >
2023-09-10 12:35:02 -05:00
< p >
2023-09-11 21:09:27 -05:00
Step length : < input type = " number " name = " inputStepLength " min = 1000 step = 1000 value = % inputStepLength % > milliseconds < br >
Cycle ID : < input type = " number " name = " inputCycleID " min = 1 value = % inputCycleID % > < br >
Number of transmitters : < input type = " number " name = " inputNtransmitters " min = 1 value = % inputNtransmitters % > < br >
2023-09-10 12:35:02 -05:00
< / p >
2023-09-05 20:41:55 -05:00
< ! - - This field is hidden so people don ' t change the submit time ( it will be wrong ) .
The value is automatically filled in with JS . - - >
< input type = " hidden " name = " inputTimeUnix " id = " js_time_unix " >
2023-09-02 18:45:50 -05:00
2023-09-04 21:53:09 -05:00
< ! - - Extra fields just in case I need them - - >
2023-09-05 20:41:55 -05:00
< input type = " hidden " name = " inputFloat " value = % inputFloat % >
2023-09-04 21:53:09 -05:00
2023-09-02 22:13:11 -05:00
< input type = " submit " value = " Submit " " >
2023-08-22 12:23:47 -05:00
< / form >
2023-09-05 11:08:01 -05:00
< iframe style = " display:none " name = " hidden-form " id = " hidden-form " > < / iframe >
2023-09-26 20:57:41 -05:00
< br > < hr >
< h2 > Network Settings < / h2 >
< form action = " /get2 " accept - charset = utf - 8 >
2023-09-27 20:12:38 -05:00
< p > Network Access :
2023-09-26 20:57:41 -05:00
< select name = " inputNetwork " id = " network " >
< option value = " 0 " > Access Point < / option >
2023-09-27 20:12:38 -05:00
< option value = " 1 " > Existing Wireless Network ( advanced ) < / option >
2023-09-26 20:57:41 -05:00
< / select > < br >
2023-09-27 20:12:38 -05:00
Existing Wireless Network SSID : < input type = " text " name = " inputSSID " value = " %inputSSID% " > < br >
Existing Wireless Network Password : < input type = " password " name = " inputPassword " value = " %inputPassword% " > < br >
< / p > < p >
Access Point : Connect to wireless network " vulpes " and point your browser to URL < a href = " http://192.168.0.1 " > http : //192.168.0.1</a> (http, not http<b>s</b>)<br>
2023-09-27 20:43:01 -05:00
Existing Network ( advanced ) : Connect to the same existing network and use the proper IP address ( useful if you have access to the router or a serial connection ) . < br >
If an existing network can ' t be connected to , an access point will be set up .
2023-09-26 20:57:41 -05:00
< / p >
2023-09-27 20:12:38 -05:00
< input type = " submit " value = " Submit and Reboot " >
2023-09-26 20:57:41 -05:00
< / form >
< iframe style = " display:none " name = " hidden-form02 " id = " hidden-form02 " > < / iframe >
2023-09-06 20:14:16 -05:00
< script type = " text/javascript " >
< / script >
2023-08-22 12:23:47 -05:00
< / body > < / html > ) rawliteral " ;
2023-08-26 20:55:28 -05:00
2023-08-22 12:23:47 -05:00
void notFound ( AsyncWebServerRequest * request ) {
request - > send ( 404 , " text/plain " , " Not found " ) ;
}
String readFile ( fs : : FS & fs , const char * path ) {
2023-08-22 14:13:47 -05:00
//Serial.printf("Reading file: %s\r\n", path);
2023-08-22 12:23:47 -05:00
File file = fs . open ( path , " r " ) ;
if ( ! file | | file . isDirectory ( ) ) {
Serial . println ( " - empty file or failed to open file " ) ;
return String ( ) ;
}
2023-08-22 14:13:47 -05:00
//Serial.println("- read from file:");
2023-08-22 12:23:47 -05:00
String fileContent ;
while ( file . available ( ) ) {
fileContent + = String ( ( char ) file . read ( ) ) ;
}
file . close ( ) ;
2023-08-22 14:13:47 -05:00
//Serial.println(fileContent);
2023-08-22 12:23:47 -05:00
return fileContent ;
}
void writeFile ( fs : : FS & fs , const char * path , const char * message ) {
Serial . printf ( " Writing file: %s \r \n " , path ) ;
File file = fs . open ( path , " w " ) ;
if ( ! file ) {
Serial . println ( " - failed to open file for writing " ) ;
return ;
}
if ( file . print ( message ) ) {
Serial . println ( " - file written " ) ;
} else {
Serial . println ( " - write failed " ) ;
}
file . close ( ) ;
}
2023-08-31 11:52:11 -05:00
// Replaces placeholder in web UI with stored values
2023-08-22 12:23:47 -05:00
String processor ( const String & var ) {
//Serial.println(var);
2023-09-16 09:51:39 -05:00
if ( var = = " inputCustomMsg " ) {
return readFile ( SPIFFS , " /inputCustomMsg.txt " ) ;
2023-08-22 12:23:47 -05:00
}
2023-08-31 20:41:24 -05:00
else if ( var = = " inputSend " ) {
return readFile ( SPIFFS , " /inputSend.txt " ) ;
2023-08-22 12:23:47 -05:00
}
2023-08-31 21:35:49 -05:00
else if ( var = = " inputWPM " ) {
return readFile ( SPIFFS , " /inputWPM.txt " ) ;
}
else if ( var = = " inputMsg " ) {
return readFile ( SPIFFS , " /inputMsg.txt " ) ;
}
2023-09-10 12:35:02 -05:00
else if ( var = = " inputStepLength " ) {
return readFile ( SPIFFS , " /inputStepLength.txt " ) ;
}
else if ( var = = " inputCycleID " ) {
return readFile ( SPIFFS , " /inputCycleID.txt " ) ;
}
else if ( var = = " inputNtransmitters " ) {
return readFile ( SPIFFS , " /inputNtransmitters.txt " ) ;
}
2023-09-26 20:57:41 -05:00
else if ( var = = " inputNetwork " ) {
return readFile ( SPIFFS , " /inputNetwork.txt " ) ;
}
else if ( var = = " inputSSID " ) {
return readFile ( SPIFFS , " /inputSSID.txt " ) ;
}
else if ( var = = " inputPassword " ) {
return readFile ( SPIFFS , " /inputPassword.txt " ) ;
}
2023-08-22 12:23:47 -05:00
else if ( var = = " inputFloat " ) {
return readFile ( SPIFFS , " /inputFloat.txt " ) ;
2023-09-04 21:53:09 -05:00
} else if ( var = = " inputStartTimeUnix " ) {
2023-09-06 20:14:16 -05:00
// Webform breaks if this value is empty.
2023-09-06 18:08:36 -05:00
String temp = readFile ( SPIFFS , " /inputStartTimeUnix.txt " ) ;
if ( temp = = " " ) {
temp = " 0 " ;
}
return temp ;
2023-09-05 20:41:55 -05:00
}
2023-08-22 12:23:47 -05:00
return String ( ) ;
}
2023-09-27 20:12:38 -05:00
// https://www.thegeekpub.com/276838/how-to-reset-an-arduino-using-code/
void ( * resetFunc ) ( void ) = 0 ; // create a standard reset function
2023-09-13 21:06:16 -05:00
// Set up arduinomorse pin and default WPM
2023-09-16 09:16:35 -05:00
LEDMorseSender sender_blink ( blinker , 10.0f ) ; //f makes it a float
LEDMorseSender sender_key ( keyer , 10.0f ) ;
2023-09-05 20:41:55 -05:00
2023-08-27 22:35:16 -05:00
//================================================================================
// setup(): stuff that only gets done once, after power up (KB1OIQ's description)
//================================================================================
2023-08-22 12:23:47 -05:00
void setup ( ) {
Serial . begin ( 115200 ) ;
2023-08-22 14:13:47 -05:00
2023-09-13 21:06:16 -05:00
// Get arduinomorse ready to go
2023-09-15 19:58:46 -05:00
sender_blink . setup ( ) ;
sender_key . setup ( ) ;
2023-09-12 21:32:11 -05:00
2023-09-08 10:39:24 -05:00
pinMode ( alarmPin , INPUT_PULLUP ) ; // Set alarm pin as pullup
2023-09-02 18:45:50 -05:00
if ( ! rtc . begin ( ) ) {
Serial . println ( " Couldn't find RTC " ) ;
Serial . flush ( ) ;
while ( 1 ) delay ( 10 ) ;
}
if ( rtc . lostPower ( ) ) {
Serial . println ( " RTC lost power, let's set the time! " ) ;
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
rtc . adjust ( DateTime ( __DATE__ , __TIME__ ) ) ;
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
//rtc.adjust(DateTime(2023, 9, 2, 17, 32, 0));
}
2023-09-19 11:11:46 -05:00
// Report the RTC time after waiting two seconds
// https://amiok.net/gitea/W1CDN/vulpes/issues/50#issuecomment-1376
2023-09-25 21:12:25 -05:00
Serial . println ( " Wait 2s for RTC " ) ;
2023-09-19 11:11:46 -05:00
delay ( 2000 ) ;
2023-09-25 21:12:25 -05:00
Serial . println ( " RTC time on startup: " ) ;
2023-09-10 12:35:02 -05:00
Serial . println ( rtc . now ( ) . unixtime ( ) ) ;
Serial . println ( rtc . now ( ) . timestamp ( ) ) ;
2023-09-08 10:39:24 -05:00
// Are there any RTC alarms set?
2023-09-08 15:00:48 -05:00
DateTime alarm_one = rtc . getAlarm1 ( ) ; // Get the current time
char buff [ ] = " Alarm 1 set for at hh:mm:ss DDD, DD MMM YYYY " ;
Serial . print ( alarm_one . toString ( buff ) ) ;
Serial . println ( " (only HH:MM:SS day-of-month are accurate) " ) ;
2023-09-08 10:39:24 -05:00
2023-08-22 14:13:47 -05:00
// Initialize the output variables as outputs
2023-09-04 20:23:14 -05:00
pinMode ( keyer , OUTPUT ) ;
2023-09-15 19:58:46 -05:00
pinMode ( blinker , OUTPUT ) ;
2023-08-22 14:13:47 -05:00
// Set outputs to LOW
2023-09-04 20:23:14 -05:00
digitalWrite ( keyer , LOW ) ;
2023-09-15 19:58:46 -05:00
digitalWrite ( blinker , LOW ) ;
2023-08-22 14:13:47 -05:00
2023-08-22 12:23:47 -05:00
// Initialize SPIFFS
2023-08-31 09:10:30 -05:00
SPIFFS . begin ( true ) ;
2023-08-22 12:23:47 -05:00
if ( ! SPIFFS . begin ( true ) ) {
Serial . println ( " An Error has occurred while mounting SPIFFS " ) ;
return ;
}
if ( ! SPIFFS . begin ( ) ) {
Serial . println ( " An Error has occurred while mounting SPIFFS " ) ;
return ;
}
2023-09-08 15:07:57 -05:00
2023-08-26 20:55:28 -05:00
// Read in existing data
2023-09-16 09:51:39 -05:00
yourInputCustomMsg = readFile ( SPIFFS , " /inputCustomMsg.txt " ) ;
2023-08-31 20:41:24 -05:00
yourInputSend = readFile ( SPIFFS , " /inputSend.txt " ) . toInt ( ) ;
2023-09-16 09:16:35 -05:00
yourInputWPM = readFile ( SPIFFS , " /inputWPM.txt " ) . toFloat ( ) ;
2023-08-31 21:35:49 -05:00
yourInputMsg = readFile ( SPIFFS , " /inputMsg.txt " ) . toInt ( ) ;
2023-08-31 09:10:30 -05:00
yourInputFloat = readFile ( SPIFFS , " /inputFloat.txt " ) . toFloat ( ) ;
2023-09-05 16:55:42 -05:00
yourInputStartTimeUnix = readFile ( SPIFFS , " /inputStartTimeUnix.txt " ) . toInt ( ) ;
2023-09-10 12:35:02 -05:00
yourInputStepLength = readFile ( SPIFFS , " /inputStepLength.txt " ) . toInt ( ) ;
yourInputCycleID = readFile ( SPIFFS , " /inputCycleID.txt " ) . toInt ( ) ;
yourInputNtransmitters = readFile ( SPIFFS , " /inputNtransmitters.txt " ) . toInt ( ) ;
2023-09-26 20:57:41 -05:00
yourInputNetwork = readFile ( SPIFFS , " /inputNetwork.txt " ) . toInt ( ) ;
yourInputSSID = readFile ( SPIFFS , " /inputSSID.txt " ) ;
yourInputPassword = readFile ( SPIFFS , " /inputPassword.txt " ) ;
2023-09-15 21:44:19 -05:00
// Set WPM from saved value
sender_blink . setWPM ( yourInputWPM ) ;
sender_key . setWPM ( yourInputWPM ) ;
2023-08-26 20:55:28 -05:00
2023-09-01 10:01:49 -05:00
// On restart, keep doing what you were doing before
yourInputMsg_old = yourInputMsg ;
if ( yourInputMsg = = 0 ) {
2023-09-16 09:51:39 -05:00
sender_blink . setMessage ( yourInputCustomMsg ) ;
sender_key . setMessage ( yourInputCustomMsg ) ;
2023-09-01 10:01:49 -05:00
} else if ( yourInputMsg = = 1 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " moe " ) ) ;
sender_key . setMessage ( String ( " moe " ) ) ;
2023-09-01 10:01:49 -05:00
} else if ( yourInputMsg = = 2 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " moi " ) ) ;
sender_key . setMessage ( String ( " moi " ) ) ;
2023-09-01 10:01:49 -05:00
} else if ( yourInputMsg = = 3 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " mos " ) ) ;
sender_key . setMessage ( String ( " mos " ) ) ;
2023-09-01 10:01:49 -05:00
} else if ( yourInputMsg = = 4 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " moh " ) ) ;
sender_key . setMessage ( String ( " moh " ) ) ;
2023-09-01 10:01:49 -05:00
} else if ( yourInputMsg = = 5 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " mo5 " ) ) ;
sender_key . setMessage ( String ( " mo5 " ) ) ;
2023-09-01 10:01:49 -05:00
}
2023-09-25 21:36:37 -05:00
WiFi . setHostname ( " vulpes " ) ;
2023-09-26 20:57:41 -05:00
if ( yourInputNetwork = = 1 ) {
2023-09-25 21:36:37 -05:00
// Attach to existing wifi
WiFi . mode ( WIFI_STA ) ;
2023-09-26 20:57:41 -05:00
const char * ssid_char = yourInputSSID . c_str ( ) ;
const char * password_char = yourInputPassword . c_str ( ) ;
WiFi . begin ( ssid_char , password_char ) ;
2023-09-25 21:36:37 -05:00
if ( WiFi . waitForConnectResult ( ) ! = WL_CONNECTED ) {
2023-09-27 20:43:01 -05:00
Serial . println ( " WiFi Failed! Setting up access point 'vulpes'... " ) ;
2023-09-26 20:57:41 -05:00
// If you fail to connect, act as new access point
2023-09-27 20:43:01 -05:00
WiFi . disconnect ( true ) ;
2023-09-26 20:57:41 -05:00
WiFi . softAPConfig ( local_ip , gateway , subnet ) ;
WiFi . softAP ( ssid_ap , password_ap ) ;
2023-09-27 20:43:01 -05:00
// update the file so the webform is right
writeFile ( SPIFFS , " /inputNetwork.txt " , " 0 " ) ;
2023-09-26 20:57:41 -05:00
//return;
2023-09-25 21:36:37 -05:00
}
Serial . print ( " IP Address: " ) ;
Serial . println ( WiFi . localIP ( ) ) ;
2023-09-26 20:57:41 -05:00
} else if ( yourInputNetwork = = 0 ) {
2023-09-25 21:36:37 -05:00
// Act as new access point
WiFi . softAPConfig ( local_ip , gateway , subnet ) ;
WiFi . softAP ( ssid_ap , password_ap ) ;
2023-08-22 12:23:47 -05:00
}
2023-09-25 21:36:37 -05:00
2023-08-22 12:23:47 -05:00
// Send web page with input fields to client
server . on ( " / " , HTTP_GET , [ ] ( AsyncWebServerRequest * request ) {
request - > send_P ( 200 , " text/html " , index_html , processor ) ;
} ) ;
2023-09-26 20:57:41 -05:00
// Form 1
2023-09-16 09:51:39 -05:00
// Send a GET request to <ESP_IP>/get?inputCustomMsg=<inputMessage>
2023-08-22 12:23:47 -05:00
server . on ( " /get " , HTTP_GET , [ ] ( AsyncWebServerRequest * request ) {
String inputMessage ;
2023-09-16 09:51:39 -05:00
// GET inputCustomMsg value on <ESP_IP>/get?inputCustomMsg=<inputMessage>
if ( request - > hasParam ( PARAM_CMSG ) ) {
inputMessage = request - > getParam ( PARAM_CMSG ) - > value ( ) ;
// arduinomorse needs lowercase characters
std : : transform ( inputMessage . begin ( ) , inputMessage . end ( ) , inputMessage . begin ( ) , : : tolower ) ;
writeFile ( SPIFFS , " /inputCustomMsg.txt " , inputMessage . c_str ( ) ) ;
yourInputCustomMsg = inputMessage ;
2023-08-22 12:23:47 -05:00
}
2023-08-31 20:41:24 -05:00
// GET inputSend value on <ESP_IP>/get?inputSend=<inputMessage>
if ( request - > hasParam ( PARAM_SEND ) ) {
inputMessage = request - > getParam ( PARAM_SEND ) - > value ( ) ;
writeFile ( SPIFFS , " /inputSend.txt " , inputMessage . c_str ( ) ) ;
yourInputSend = inputMessage . toInt ( ) ;
2023-09-05 20:41:55 -05:00
// if not running a program, set the program running off
2023-09-14 21:02:28 -05:00
//if(yourInputSend != 2){
// Cease all programs on new input
2023-09-09 16:01:41 -05:00
startProgram = false ;
programRunning = false ;
2023-09-14 21:02:28 -05:00
//}
2023-08-22 12:23:47 -05:00
}
2023-08-31 21:35:49 -05:00
// GET inputWPM value on <ESP_IP>/get?inputWPM=<inputMessage>
if ( request - > hasParam ( PARAM_WPM ) ) {
inputMessage = request - > getParam ( PARAM_WPM ) - > value ( ) ;
writeFile ( SPIFFS , " /inputWPM.txt " , inputMessage . c_str ( ) ) ;
2023-09-15 21:44:19 -05:00
yourInputWPM = inputMessage . toFloat ( ) ;
sender_blink . setWPM ( yourInputWPM ) ;
sender_key . setWPM ( yourInputWPM ) ;
2023-08-31 21:35:49 -05:00
}
// GET inputMsg value on <ESP_IP>/get?inputMsg=<inputMessage>
if ( request - > hasParam ( PARAM_MSG ) ) {
inputMessage = request - > getParam ( PARAM_MSG ) - > value ( ) ;
writeFile ( SPIFFS , " /inputMsg.txt " , inputMessage . c_str ( ) ) ;
2023-09-01 09:39:00 -05:00
// save previous state
yourInputMsg_old = yourInputMsg ;
2023-08-31 21:35:49 -05:00
yourInputMsg = inputMessage . toInt ( ) ;
2023-09-14 21:02:28 -05:00
// Check the message every time the form is submitted.
if ( yourInputMsg = = 0 ) {
2023-09-16 09:51:39 -05:00
sender_blink . setMessage ( yourInputCustomMsg ) ;
sender_key . setMessage ( yourInputCustomMsg ) ;
2023-09-14 21:02:28 -05:00
} else if ( yourInputMsg = = 1 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " moe " ) ) ;
sender_key . setMessage ( String ( " moe " ) ) ;
2023-09-14 21:02:28 -05:00
} else if ( yourInputMsg = = 2 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " moi " ) ) ;
sender_key . setMessage ( String ( " moi " ) ) ;
2023-09-14 21:02:28 -05:00
} else if ( yourInputMsg = = 3 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " mos " ) ) ;
sender_key . setMessage ( String ( " mos " ) ) ;
2023-09-14 21:02:28 -05:00
} else if ( yourInputMsg = = 4 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " moh " ) ) ;
sender_key . setMessage ( String ( " moh " ) ) ;
2023-09-14 21:02:28 -05:00
} else if ( yourInputMsg = = 5 ) {
2023-09-15 19:58:46 -05:00
sender_blink . setMessage ( String ( " mo5 " ) ) ;
sender_key . setMessage ( String ( " mo5 " ) ) ;
2023-09-14 21:02:28 -05:00
}
2023-08-31 21:35:49 -05:00
}
2023-09-10 12:35:02 -05:00
// GET inputStepLength value on <ESP_IP>/get?inputStepLength=<inputMessage>
if ( request - > hasParam ( PARAM_STEPLENGTH ) ) {
inputMessage = request - > getParam ( PARAM_STEPLENGTH ) - > value ( ) ;
writeFile ( SPIFFS , " /inputStepLength.txt " , inputMessage . c_str ( ) ) ;
yourInputStepLength = inputMessage . toInt ( ) ;
}
// GET inputCycleID value on <ESP_IP>/get?inputCycleID=<inputMessage>
if ( request - > hasParam ( PARAM_CYCLEID ) ) {
inputMessage = request - > getParam ( PARAM_CYCLEID ) - > value ( ) ;
writeFile ( SPIFFS , " /inputCycleID.txt " , inputMessage . c_str ( ) ) ;
yourInputCycleID = inputMessage . toInt ( ) ;
}
// GET inputNtransmitters value on <ESP_IP>/get?inputNtransmitters=<inputMessage>
if ( request - > hasParam ( PARAM_NTRANS ) ) {
inputMessage = request - > getParam ( PARAM_NTRANS ) - > value ( ) ;
writeFile ( SPIFFS , " /inputNtransmitters.txt " , inputMessage . c_str ( ) ) ;
yourInputNtransmitters = inputMessage . toInt ( ) ;
}
2023-09-02 18:45:50 -05:00
// GET inputTimeUnix value on <ESP_IP>/get?inputTimeUnix=<inputMessage>
if ( request - > hasParam ( PARAM_TIME ) ) {
inputMessage = request - > getParam ( PARAM_TIME ) - > value ( ) ;
2023-09-02 22:11:51 -05:00
//https://stackoverflow.com/a/22733127/2152245
yourInputTime = atol ( inputMessage . c_str ( ) ) ;
2023-09-06 22:07:48 -05:00
Serial . print ( " yourInputTime: " ) ;
2023-09-02 18:45:50 -05:00
Serial . println ( yourInputTime ) ;
2023-09-02 20:02:59 -05:00
// update the RTC time
rtc . adjust ( DateTime ( yourInputTime ) ) ;
2023-09-08 15:00:48 -05:00
DateTime now = rtc . now ( ) ;
2023-09-06 22:07:48 -05:00
// Might work to fix random errors? If date is far in the future,
// try to update again.
2023-09-08 15:00:48 -05:00
// replace if with while if you want it to try a bunch...
if ( now . year ( ) > 2040 ) {
Serial . print ( " Year is " ) ;
Serial . println ( now . year ( ) ) ;
2023-09-06 22:07:48 -05:00
Serial . println ( " RTC can't set time. Trying again. " ) ;
rtc . adjust ( DateTime ( yourInputTime ) ) ;
}
2023-09-08 15:00:48 -05:00
2023-09-02 22:11:51 -05:00
Serial . print ( " UTC time from browser: " ) ;
Serial . print ( now . year ( ) , DEC ) ;
Serial . print ( ' / ' ) ;
Serial . print ( now . month ( ) , DEC ) ;
Serial . print ( ' / ' ) ;
Serial . print ( now . day ( ) , DEC ) ;
Serial . print ( " ( " ) ;
Serial . print ( now . dayOfTheWeek ( ) ) ;
Serial . print ( " ) " ) ;
Serial . print ( now . hour ( ) , DEC ) ;
Serial . print ( ' : ' ) ;
Serial . print ( now . minute ( ) , DEC ) ;
Serial . print ( ' : ' ) ;
Serial . print ( now . second ( ) , DEC ) ;
Serial . println ( ) ;
2023-09-06 22:07:48 -05:00
Serial . print ( " rtc.now().unixtime(): " ) ;
Serial . println ( rtc . now ( ) . unixtime ( ) ) ;
2023-09-02 18:45:50 -05:00
}
2023-08-22 12:23:47 -05:00
// GET inputFloat value on <ESP_IP>/get?inputFloat=<inputMessage>
2023-08-30 22:26:23 -05:00
if ( request - > hasParam ( PARAM_FLOAT ) ) {
2023-08-22 12:23:47 -05:00
inputMessage = request - > getParam ( PARAM_FLOAT ) - > value ( ) ;
writeFile ( SPIFFS , " /inputFloat.txt " , inputMessage . c_str ( ) ) ;
2023-08-31 09:10:30 -05:00
yourInputFloat = inputMessage . toFloat ( ) ;
2023-08-22 12:23:47 -05:00
}
2023-09-04 21:53:09 -05:00
// GET inputStartTimeUnix value on <ESP_IP>/get?inputStartTimeUnix=<inputMessage>
if ( request - > hasParam ( PARAM_START ) ) {
inputMessage = request - > getParam ( PARAM_START ) - > value ( ) ;
2023-09-05 20:41:55 -05:00
Serial . println ( inputMessage ) ;
// if a start time isn't entered, don't overwrite the old one
//if(!(inputMessage != NULL && inputMessage[0] == '\0')){
writeFile ( SPIFFS , " /inputStartTimeUnix.txt " , inputMessage . c_str ( ) ) ;
yourInputStartTimeUnix = atol ( inputMessage . c_str ( ) ) ;
//}
2023-09-04 21:53:09 -05:00
Serial . println ( yourInputStartTimeUnix ) ;
2023-09-08 08:39:14 -05:00
// Use alarm built into RTC
2023-09-08 15:00:48 -05:00
rtc . setAlarm1 ( DateTime ( yourInputStartTimeUnix ) , DS3231_A1_Date ) ;
2023-09-08 08:39:14 -05:00
//rtc.setAlarm1(DateTime(2020, 6, 25, 15, 34, 0), DS3231_A2_Date);
2023-09-08 15:00:48 -05:00
DateTime alarm_one = rtc . getAlarm1 ( ) ; // Get the current alarm time
char buff [ ] = " Alarm 1 set for at hh:mm:ss DDD, DD MMM YYYY " ;
Serial . print ( alarm_one . toString ( buff ) ) ;
Serial . println ( " (only HH:MM:SS day-of-month are accurate) " ) ;
2023-09-04 21:53:09 -05:00
}
2023-09-07 20:20:53 -05:00
// https://techtutorialsx.com/2018/01/14/esp32-arduino-http-server-external-and-internal-redirects/
2023-09-06 21:36:10 -05:00
request - > redirect ( " / " ) ;
2023-08-22 12:23:47 -05:00
} ) ;
2023-09-26 20:57:41 -05:00
// Form 2
server . on ( " /get2 " , HTTP_GET , [ ] ( AsyncWebServerRequest * request ) {
String inputMessage ;
/// GET inputNetwork value on <ESP_IP>/get2?inputNetwork=<inputMessage>
if ( request - > hasParam ( PARAM_NETWORK ) ) {
inputMessage = request - > getParam ( PARAM_NETWORK ) - > value ( ) ;
writeFile ( SPIFFS , " /inputNetwork.txt " , inputMessage . c_str ( ) ) ;
yourInputNetwork = inputMessage . toInt ( ) ;
Serial . println ( yourInputNetwork ) ;
}
/// GET inputSSID value on <ESP_IP>/get2?inputSSID=<inputMessage>
if ( request - > hasParam ( PARAM_SSID ) ) {
inputMessage = request - > getParam ( PARAM_SSID ) - > value ( ) ;
writeFile ( SPIFFS , " /inputSSID.txt " , inputMessage . c_str ( ) ) ;
yourInputSSID = inputMessage ;
Serial . println ( yourInputSSID ) ;
}
/// GET inputNetwork value on <ESP_IP>/get2?inputNetwork=<inputMessage>
if ( request - > hasParam ( PARAM_PASSWORD ) ) {
inputMessage = request - > getParam ( PARAM_PASSWORD ) - > value ( ) ;
writeFile ( SPIFFS , " /inputPassword.txt " , inputMessage . c_str ( ) ) ;
yourInputPassword = inputMessage ;
Serial . println ( yourInputPassword ) ;
}
2023-09-27 20:12:38 -05:00
// Shouldn't need to do this if using this form.
//request->redirect("/");
resetFunc ( ) ; // reset the Arduino via software function
2023-09-26 20:57:41 -05:00
} ) ;
2023-08-22 12:23:47 -05:00
server . onNotFound ( notFound ) ;
server . begin ( ) ;
2023-08-27 22:35:16 -05:00
2023-08-22 12:23:47 -05:00
}
void loop ( ) {
2023-09-12 21:32:11 -05:00
2023-09-10 12:35:02 -05:00
// This statement from https://github.com/garrysblog/DS3231-Alarm-With-Adafruit-RTClib-Library/blob/master/DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired/DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired.ino
// Check if alarm by polling SQW alarm pin
if ( ( yourInputSend = = 2 ) & ( digitalRead ( alarmPin ) = = LOW ) ) {
// Print current time and date
DateTime now = rtc . now ( ) ; // Get the current time
char buff [ ] = " Alarm triggered at hh:mm:ss DDD, DD MMM YYYY " ;
Serial . println ( now . toString ( buff ) ) ;
startProgram = true ;
// Disable and clear alarm
rtc . clearAlarm ( 1 ) ;
rtc . clearAlarm ( 2 ) ; // clear the other one just in case
}
// Once alarm has started the program, set things up to run
2023-09-15 12:22:02 -05:00
if ( startProgram = = true ) {
2023-09-14 17:09:55 -05:00
//Serial.println("Start sending");
2023-09-14 21:02:28 -05:00
start_millis = millis ( ) + ( ( yourInputCycleID - 1 ) * yourInputStepLength ) ;
stop_millis = start_millis + yourInputStepLength ;
2023-09-15 12:22:02 -05:00
if ( yourInputCycleID = = 1 ) {
pause_until_millis = stop_millis + ( yourInputStepLength * ( yourInputNtransmitters - 1 ) ) ;
} else {
2023-09-14 21:02:28 -05:00
// Subtract 2 rather than 1 here to account for start_millis duration at beginning of repeat.
2023-09-15 12:22:02 -05:00
pause_until_millis = stop_millis + ( yourInputStepLength * ( yourInputNtransmitters - 2 ) ) ;
}
2023-09-10 12:35:02 -05:00
programRunning = true ;
startProgram = false ;
}
2023-08-31 21:35:49 -05:00
2023-08-31 20:41:24 -05:00
// if you want to send continuous code, and it's not sending, then start it up
2023-09-14 21:02:28 -05:00
if ( ( yourInputSend = = 1 ) ) {
2023-09-15 19:58:46 -05:00
// If not sending, start sending. Yes, these need to be separate statements.
if ( ! sender_blink . continueSending ( ) ) {
sender_blink . startSending ( ) ;
}
if ( ! sender_key . continueSending ( ) ) {
sender_key . startSending ( ) ;
}
2023-08-31 20:41:24 -05:00
// if you want to send cycle code and it's not sending, then start it up
2023-09-14 21:02:28 -05:00
} else if ( ( yourInputSend = = 2 ) & ( programRunning = = true ) ) {
if ( ( millis ( ) < start_millis ) ) {
// Shut the pin off manually
digitalWrite ( blinker , LOW ) ;
2023-09-15 19:58:46 -05:00
digitalWrite ( keyer , LOW ) ;
2023-09-14 21:02:28 -05:00
} else if ( ( millis ( ) > = start_millis ) & ( millis ( ) < = stop_millis ) ) {
2023-09-15 19:58:46 -05:00
// If not sending, start sending. Yes, these need to be separate statements
// for the blinker and keyer.
if ( ! sender_blink . continueSending ( ) ) {
sender_blink . startSending ( ) ;
}
if ( ! sender_key . continueSending ( ) ) {
sender_key . startSending ( ) ;
2023-09-14 12:44:10 -05:00
}
2023-09-14 21:02:28 -05:00
} else if ( ( millis ( ) > = stop_millis ) & ( millis ( ) < = pause_until_millis ) ) {
2023-09-14 12:46:35 -05:00
// do nothing in this case -- in between cycles
2023-09-14 21:02:28 -05:00
// Shut the pin off manually
digitalWrite ( blinker , LOW ) ;
2023-09-15 19:58:46 -05:00
digitalWrite ( keyer , LOW ) ;
2023-09-14 21:02:28 -05:00
} else if ( ( millis ( ) > = pause_until_millis ) ) {
2023-09-14 12:44:10 -05:00
startProgram = true ;
2023-09-13 21:54:43 -05:00
}
2023-09-09 16:01:41 -05:00
// if the cycle program is not running
2023-09-10 12:35:02 -05:00
} else if ( ( yourInputSend = = 2 ) & ( programRunning = = false ) ) {
2023-09-14 17:09:55 -05:00
// do we need something here?
2023-08-30 22:04:32 -05:00
// if you don't want to send code
2023-09-14 12:44:10 -05:00
} else if ( yourInputSend = = 0 ) {
2023-09-14 21:02:28 -05:00
// Shut the pin off manually
digitalWrite ( blinker , LOW ) ;
2023-09-15 19:58:46 -05:00
digitalWrite ( keyer , LOW ) ;
2023-08-30 22:04:32 -05:00
}
2023-08-22 12:23:47 -05:00
}