Compare commits

7 Commits

Author SHA1 Message Date
269cbfdd22 Shelve. 2023-09-16 19:17:31 -05:00
c48c624f71 Shelve. 2023-09-16 17:04:22 -05:00
dccd3d27f4 Merge pull request 'Add custom message ability' (#47) from custom-message into main
Reviewed-on: #47
2023-09-16 15:48:03 -05:00
2618d82e12 Add custom message ability 2023-09-16 09:51:39 -05:00
08b1bdf3fd Merge pull request 'Change WPM on webform' (#45) from wpm into main
Reviewed-on: #45
2023-09-16 09:17:17 -05:00
d973bbf19a Clean up. 2023-09-16 09:16:35 -05:00
f4287eba7b Control WPM from webform. 2023-09-15 21:44:19 -05:00

View File

@ -38,10 +38,10 @@ const int alarmPin = 4; // pin to monitor for RTC alarms
const char* ssid = WIFI_SSID; const char* ssid = WIFI_SSID;
const char* password = WIFI_PASSWORD; const char* password = WIFI_PASSWORD;
const char* PARAM_STRING = "inputString";
const char* PARAM_SEND = "inputSend"; const char* PARAM_SEND = "inputSend";
const char* PARAM_WPM = "inputWPM"; const char* PARAM_WPM = "inputWPM";
const char* PARAM_MSG = "inputMsg"; const char* PARAM_MSG = "inputMsg";
const char* PARAM_CMSG = "inputCustomMsg";
const char* PARAM_FLOAT = "inputFloat"; const char* PARAM_FLOAT = "inputFloat";
const char* PARAM_TIME = "inputTimeUnix"; const char* PARAM_TIME = "inputTimeUnix";
const char* PARAM_START = "inputStartTimeUnix"; const char* PARAM_START = "inputStartTimeUnix";
@ -51,11 +51,11 @@ const char* PARAM_CYCLEID = "inputCycleID";
const char* PARAM_NTRANS = "inputNtransmitters"; const char* PARAM_NTRANS = "inputNtransmitters";
// Global variables // Global variables
String yourInputString;
int yourInputSend; int yourInputSend;
int yourInputWPM; int yourInputWPM;
int yourInputMsg; int yourInputMsg;
int yourInputMsg_old; // to save previous state and check changes int yourInputMsg_old; // to save previous state and check changes
String yourInputCustomMsg;
float yourInputFloat; float yourInputFloat;
uint32_t yourInputTime; //to keep time uint32_t yourInputTime; //to keep time
uint32_t yourInputStartTimeUnix; uint32_t yourInputStartTimeUnix;
@ -68,11 +68,19 @@ long start_millis = 0;
long stop_millis = 0; long stop_millis = 0;
long pause_until_millis = 0; long pause_until_millis = 0;
// HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) // HTML web page to handle input fields
const char index_html[] PROGMEM = R"rawliteral( const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head> <!DOCTYPE HTML><html><head>
<link rel="icon" href="data:,"> <link rel="icon" href="data:,">
<title>ESP Input Form</title> <title>Vulpes Radio Orienteering Controller</title>
<style>
.inv_message {
display: none;
}
.inv_program {
display: none;
}
</style>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript"> <script type="text/javascript">
// Utility from https://webreflection.medium.com/using-the-input-datetime-local-9503e7efdce // Utility from https://webreflection.medium.com/using-the-input-datetime-local-9503e7efdce
@ -123,49 +131,89 @@ const char index_html[] PROGMEM = R"rawliteral(
<h2>General Settings</h2> <h2>General Settings</h2>
<p>Sending program: <p>Sending program:
<select name="inputSend" id="send-program"> <select name="inputSend" id="send-program">
<option value="0" >0 - Off</option> <option value="0">0 - Off</option>
<option value="1">1 - Continuous</option> <option value="1">1 - Continuous</option>
<option value="2">2 - Cycle</option> <option value="2">2 - Cycle</option>
</select><br> </select><br>
Message: Message:
<select name="inputMsg" id="message"> <select name="inputMsg" id="message">
<option value="0">0 - TEST TEST TEST DE W1CDN</option> <option value="0">0 - Custom Message</option>
<option value="1">1 - MOE</option> <option value="1">1 - MOE</option>
<option value="2">2 - MOI</option> <option value="2">2 - MOI</option>
<option value="3">3 - MOS</option> <option value="3">3 - MOS</option>
<option value="4">4 - MOH</option> <option value="4">4 - MOH</option>
<option value="5">5 - MO5</option> <option value="5">5 - MO5</option>
</select></p> </select><br>
<!-- Hidden unless "0 - Custom Message" is selected -->
<span id="message0" class="inv_message">
Custom message: <input type="text" name="inputCustomMsg" value = "%inputCustomMsg%"><br>
</span>
Speed: <input type="number" name="inputWPM" value = %inputWPM%> WPM
</p>
<!-- Hidden unless "2 - Cycle" is selected -->
<span id="program2" class="inv_program">
<h2>Cycle Settings</h2> <h2>Cycle Settings</h2>
<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> <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.<br>
<p>Cycle start time <input type="datetime-local" id="js_start_time_unix_entry" /><br> Cycle start time <input type="datetime-local" id="js_start_time_unix_entry" /><br>
Current value: <b><span id=current-start></span></b> Current value: <b><span id=current-start></span></b><br>
<!-- JS converts the entered start time to a unix timestamp, and copies that value <!-- 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. --> to this hidden field so the user doesn't have to see it. -->
<input type="hidden" name="inputStartTimeUnix" id="js_start_time_unix" /></p> <input type="hidden" name="inputStartTimeUnix" id="js_start_time_unix" /></p>
<p>
Step length: <input type="number" name="inputStepLength" min=1000 step=1000 value = %inputStepLength%> milliseconds <br> 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> 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> Number of transmitters: <input type="number" name="inputNtransmitters" min=1 value = %inputNtransmitters%><br>
</p> </p>
</span>
<!-- This field is hidden so people don't change the submit time (it will be wrong). <!-- This field is hidden so people don't change the submit time (it will be wrong).
The value is automatically filled in with JS. --> The value is automatically filled in with JS. -->
<input type="hidden" name="inputTimeUnix" id="js_time_unix"> <input type="hidden" name="inputTimeUnix" id="js_time_unix">
<!-- Extra fields just in case I need them --> <!-- Extra fields just in case I need them -->
<input type="hidden" name="inputWPM" value = %inputWPM%>
<input type="hidden" name="inputString" value = %inputString%>
<input type="hidden" name="inputFloat" value = %inputFloat%> <input type="hidden" name="inputFloat" value = %inputFloat%>
<input type="submit" value="Submit""> <input type="submit" value="Submit"">
</form> </form>
<iframe style="display:none" name="hidden-form" id="hidden-form"></iframe> <iframe style="display:none" name="hidden-form" id="hidden-form"></iframe>
<script type="text/javascript"> <script type="text/javascript">
// Show more stuff depending on selected values
// https://stackoverflow.com/a/24849350
show_message = function () {
'use strict';
var vis_message = document.querySelector('.vis_message'),
target = document.getElementById("message"+this.value);
if (vis_message !== null) {
vis_message.className = 'inv_message';
}
if (target !== null ) {
target.className = 'vis_message';
}
}
show_program = function () {
'use strict';
var vis_program = document.querySelector('.vis_program'),
target = document.getElementById("program"+this.value);
if (vis_program !== null) {
vis_program.className = 'inv_program';
}
if (target !== null ) {
target.className = 'vis_program';
}
}
document
.getElementById('message')
.addEventListener('change', show_message);
document
.getElementById('send-program')
.addEventListener('change', show_program);
</script> </script>
</body></html>)rawliteral"; </body></html>)rawliteral";
@ -209,8 +257,8 @@ void writeFile(fs::FS &fs, const char * path, const char * message){
// Replaces placeholder in web UI with stored values // Replaces placeholder in web UI with stored values
String processor(const String& var){ String processor(const String& var){
//Serial.println(var); //Serial.println(var);
if(var == "inputString"){ if(var == "inputCustomMsg"){
return readFile(SPIFFS, "/inputString.txt"); return readFile(SPIFFS, "/inputCustomMsg.txt");
} }
else if(var == "inputSend"){ else if(var == "inputSend"){
return readFile(SPIFFS, "/inputSend.txt"); return readFile(SPIFFS, "/inputSend.txt");
@ -245,15 +293,8 @@ String processor(const String& var){
// Set up arduinomorse pin and default WPM // Set up arduinomorse pin and default WPM
LEDMorseSender sender_blink(blinker, 10.0f) ; // the 'f' makes sure this is a float LEDMorseSender sender_blink(blinker, 10.0f); //f makes it a float
LEDMorseSender sender_key(keyer, 10.0f) ; // the 'f' makes sure this is a float LEDMorseSender sender_key(keyer, 10.0f);
// Speed is milliseconds per dit, which is 1000 * (60 / (50 * WPM))
// 60 is 20 wpm, 120 is 10 wpm, 90 is 15 wpm, etc.
// https://morsecode.world/international/timing.html
float wpm = 10;
float ms_per_dit = 1000 * (60 / (50 * wpm));
int word_space_ms = ms_per_dit * 7;
//================================================================================ //================================================================================
// setup(): stuff that only gets done once, after power up (KB1OIQ's description) // setup(): stuff that only gets done once, after power up (KB1OIQ's description)
@ -313,21 +354,24 @@ void setup() {
} }
// Read in existing data // Read in existing data
yourInputString = readFile(SPIFFS, "/inputString.txt"); yourInputCustomMsg = readFile(SPIFFS, "/inputCustomMsg.txt");
yourInputSend = readFile(SPIFFS, "/inputSend.txt").toInt(); yourInputSend = readFile(SPIFFS, "/inputSend.txt").toInt();
yourInputWPM = readFile(SPIFFS, "/inputWPM.txt").toInt(); yourInputWPM = readFile(SPIFFS, "/inputWPM.txt").toFloat();
yourInputMsg = readFile(SPIFFS, "/inputMsg.txt").toInt(); yourInputMsg = readFile(SPIFFS, "/inputMsg.txt").toInt();
yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat();
yourInputStartTimeUnix = readFile(SPIFFS, "/inputStartTimeUnix.txt").toInt(); yourInputStartTimeUnix = readFile(SPIFFS, "/inputStartTimeUnix.txt").toInt();
yourInputStepLength = readFile(SPIFFS, "/inputStepLength.txt").toInt(); yourInputStepLength = readFile(SPIFFS, "/inputStepLength.txt").toInt();
yourInputCycleID = readFile(SPIFFS, "/inputCycleID.txt").toInt(); yourInputCycleID = readFile(SPIFFS, "/inputCycleID.txt").toInt();
yourInputNtransmitters = readFile(SPIFFS, "/inputNtransmitters.txt").toInt(); yourInputNtransmitters = readFile(SPIFFS, "/inputNtransmitters.txt").toInt();
// Set WPM from saved value
sender_blink.setWPM(yourInputWPM);
sender_key.setWPM(yourInputWPM);
// On restart, keep doing what you were doing before // On restart, keep doing what you were doing before
yourInputMsg_old = yourInputMsg; yourInputMsg_old = yourInputMsg;
if(yourInputMsg == 0){ if(yourInputMsg == 0){
sender_blink.setMessage(String("test test test de w1cdn ")); sender_blink.setMessage(yourInputCustomMsg);
sender_key.setMessage(String("test test test de w1cdn ")); sender_key.setMessage(yourInputCustomMsg);
} else if(yourInputMsg == 1){ } else if(yourInputMsg == 1){
sender_blink.setMessage(String("moe ")); sender_blink.setMessage(String("moe "));
sender_key.setMessage(String("moe ")); sender_key.setMessage(String("moe "));
@ -360,14 +404,17 @@ void setup() {
request->send_P(200, "text/html", index_html, processor); request->send_P(200, "text/html", index_html, processor);
}); });
// Send a GET request to <ESP_IP>/get?inputString=<inputMessage> // Send a GET request to <ESP_IP>/get?inputCustomMsg=<inputMessage>
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) { server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage; String inputMessage;
// GET inputString value on <ESP_IP>/get?inputString=<inputMessage> // GET inputCustomMsg value on <ESP_IP>/get?inputCustomMsg=<inputMessage>
if (request->hasParam(PARAM_STRING)) { if (request->hasParam(PARAM_CMSG)) {
inputMessage = request->getParam(PARAM_STRING)->value(); inputMessage = request->getParam(PARAM_CMSG)->value();
writeFile(SPIFFS, "/inputString.txt", inputMessage.c_str()); // arduinomorse needs lowercase characters
yourInputString = inputMessage; std::transform(inputMessage.begin(), inputMessage.end(), inputMessage.begin(), ::tolower);
writeFile(SPIFFS, "/inputCustomMsg.txt", inputMessage.c_str());
yourInputCustomMsg = inputMessage;
} }
// GET inputSend value on <ESP_IP>/get?inputSend=<inputMessage> // GET inputSend value on <ESP_IP>/get?inputSend=<inputMessage>
if (request->hasParam(PARAM_SEND)) { if (request->hasParam(PARAM_SEND)) {
@ -385,7 +432,9 @@ void setup() {
if (request->hasParam(PARAM_WPM)) { if (request->hasParam(PARAM_WPM)) {
inputMessage = request->getParam(PARAM_WPM)->value(); inputMessage = request->getParam(PARAM_WPM)->value();
writeFile(SPIFFS, "/inputWPM.txt", inputMessage.c_str()); writeFile(SPIFFS, "/inputWPM.txt", inputMessage.c_str());
yourInputWPM = inputMessage.toInt(); yourInputWPM = inputMessage.toFloat();
sender_blink.setWPM(yourInputWPM);
sender_key.setWPM(yourInputWPM);
} }
// GET inputMsg value on <ESP_IP>/get?inputMsg=<inputMessage> // GET inputMsg value on <ESP_IP>/get?inputMsg=<inputMessage>
if (request->hasParam(PARAM_MSG)) { if (request->hasParam(PARAM_MSG)) {
@ -397,8 +446,8 @@ void setup() {
// Check the message every time the form is submitted. // Check the message every time the form is submitted.
if(yourInputMsg == 0){ if(yourInputMsg == 0){
sender_blink.setMessage(String("test test test de w1cdn ")); sender_blink.setMessage(yourInputCustomMsg);
sender_key.setMessage(String("test test test de w1cdn ")); sender_key.setMessage(yourInputCustomMsg);
} else if(yourInputMsg == 1){ } else if(yourInputMsg == 1){
sender_blink.setMessage(String("moe ")); sender_blink.setMessage(String("moe "));
sender_key.setMessage(String("moe ")); sender_key.setMessage(String("moe "));