presentation-clicker/ESP32 Code/clicker/clicker.ino
2024-10-07 16:44:03 -04:00

633 lines
16 KiB
C++
Executable File

#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <Preferences.h>
#include <HTTPClient.h>
#include <Adafruit_NeoPixel.h>
#include <BleKeyboard.h>
#include <Battery.h>
Battery battery(3000, 4200, 36, 12);
BleKeyboard bleKeyboard("ESP Clicker");
Preferences prefs;
WiFiClient client;
HTTPClient http;
AsyncWebServer server(80);
Adafruit_NeoPixel led(1, 13, NEO_GRB + NEO_KHZ800);
String ssid, pass, ip_address, layer, name, serverPath;
char ssid_char[20];
char pass_char[20];
float voltage;
bool connected = false;
bool blemode;
unsigned long target_time;
int lazer_button;
String index_html;
int httpResponseCode = 0;
int LAZER = 15;
int BUTTON0 = 12;
int BUTTON1 = 14;
int BUTTON2 = 27;
int BUTTON3 = 26;
int BUTTON4 = 25;
int BUTTON5 = 33;
int BUTTON6 = 32;
int BUTTON7 = 35;
int BUTTON8 = 34;
int BUTTON9 = 39;
// Button Array
int button[10] = { BUTTON0, BUTTON1, BUTTON2, BUTTON3, BUTTON4, BUTTON5, BUTTON6, BUTTON7, BUTTON8, BUTTON9 };
// HTML web page to handle 3 input fields (input1, input2, input3)
const char index_html1[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
<title>Clicker</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f0f0f0;
}
#container {
text-align: center;
background-color: white;
padding: 20px;
border-radius: 10px;
max-width: 100%;
}
h1 {
margin-top: 0;
}
h2 {
margin-bottom: 10px;
}
form {
margin-bottom: 20px;
}
input[type="text"],
input[type="password"] {
width: 100%;
max-width: 200px;
padding: 5px;
margin-bottom: 10px;
}
button,
input[type="submit"] {
padding: 10px 20px;
cursor: pointer;
background-color: #007bff;
border: none;
color: white;
border-radius: 5px;
}
button:hover,
input[type="submit"]:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div id="container">
<h1>ESP Clicker - )rawliteral";
const char index_html2[] PROGMEM = R"rawliteral(</h1>
<hr>
<h2>Change WIFI Password</h2>
<form action="/" id="form_wifi">
SSID: <input type="text" name="ssid" id="ssid">
<br>
Password: <input type="password" name="pass" id="pass">
<br>
<input type="submit" value="Update Wifi" id="submit_wifi">
</form>
<button onclick="window.location.href='/?data=1';">Get Current Wifi Data</button>
<br>
<br>
<br>
<h2>Set Companion IP address</h2>
<form action="/" id="form_ip_address">
<input type="text" minlength="7" maxlength="15" size="1" id="ipaddress" name="ipaddress" placeholder="xxx.xxx.xxx.xxx" autocomplete="off">
<br>
<input type="submit" value="Update IP" id="submit_ip">
</form>
<button onclick="window.location.href='/?ipget=1';">Get Current Remote IP</button>
<br>
<br>
<br>
<h2>Set Companion Layer</h2>
<form action="/" id="form_Companion_layer">
<input type="number" minlength="1" maxlength="2" size="1" id="layer" name="layer" placeholder="xx" autocomplete="off">
<br>
<input type="submit" value="Update Layer" id="submit_layer">
</form>
<br>
<br>
<h2>Set Lazer Button</h2>
<form action="/" id="lazer">
<select id="lazer_dropdown" name="lazer">
<option value="-2">-- Select One --</option>
<option value="0">1</option>
<option value="1">2</option>
<option value="2">3</option>
<option value="3">4</option>
<option value="4">5</option>
<option value="5">6</option>
<option value="6">7</option>
<option value="7">8</option>
<option value="8">9</option>
<option value="9">10</option>
<option value="-1">Disable</option>
</select>
<br>
<br>
<input type="submit" value="Update Lazer Button" id="submit_lazer">
</form>
<br>
<br>
<h2>Set Device Name</h2>
<form action="/" id="form_name">
<input type="text" name="name" id="name">
<br>
<input type="submit" value="Update Name" id="submit_name">
</form>
<br>
<br>
<button onclick="window.location.href='/?voltageget=1';">Get Current Battery Voltage</button>
<script>
const lazer_form = document.getElementById('lazer');
const lazer_selector = document.getElementById('lazer_dropdown');
lazer_form.addEventListener('submit', function(event) {
// Check if the default option is selected
if (lazer_selector.value == '-2') {
// If it is, prevent the default submission behavior and show a message
event.preventDefault();
alert("Please select an option other than '-- Select One --'");
}
});
document.getElementById('submit_wifi').disabled = true;
document.getElementById('submit_ip').disabled = true;
document.getElementById('submit_layer').disabled = true;
document.addEventListener('keyup', e => {
if (document.getElementById('ssid').value == "" || document.getElementById('pass').value == "") {
document.getElementById('submit_wifi').disabled = true;
} else {
document.getElementById('submit_wifi').disabled = false;
}
if (document.getElementById("ipaddress").value == "") {
document.getElementById('submit_ip').disabled = true;
} else {
document.getElementById('submit_ip').disabled = false;
}
if (document.getElementById("layer").value == "") {
document.getElementById('submit_layer').disabled = true;
} else {
document.getElementById('submit_layer').disabled = false;
}
if (document.getElementById("name").value == "") {
document.getElementById('submit_name').disabled = true;
} else {
document.getElementById('submit_name').disabled = false;
}
});
</script>
</div>
</body>
</html>
)rawliteral";
// the setup function runs once when you press reset or power the board
void setup() {
// Initialize Memory
prefs.begin("clicker");
// Battery
battery.begin(3300, 2.24);
//Get Device Name
name = prefs.getString("NAME", name);
// Initialize Serial
Serial.begin(9600);
// Initialize NeoPixel strip object (REQUIRED)
led.begin();
// Setup pins
pinMode(LAZER, OUTPUT);
pinMode(BUTTON0, INPUT);
pinMode(BUTTON1, INPUT);
pinMode(BUTTON2, INPUT);
pinMode(BUTTON3, INPUT);
pinMode(BUTTON0, INPUT);
pinMode(BUTTON1, INPUT);
pinMode(BUTTON2, INPUT);
pinMode(BUTTON3, INPUT);
pinMode(BUTTON4, INPUT);
pinMode(BUTTON5, INPUT);
pinMode(BUTTON6, INPUT);
pinMode(BUTTON7, INPUT);
pinMode(BUTTON8, INPUT);
pinMode(BUTTON9, INPUT);
//Set up Lazer
lazer_button = prefs.getInt("LAZER_BUTTON");
digitalWrite(LAZER, LOW);
// Check for BLE Mode
blemode = prefs.getBool("BLEMODE");
if (digitalRead(BUTTON8) && digitalRead(BUTTON9)) {
prefs.putBool("BLEMODE", !blemode);
blemode = !blemode;
}
if (blemode) {
bleclicker();
}
// Initilize WIFI
WiFi.mode(WIFI_STA);
ssid = prefs.getString("SSID");
pass = prefs.getString("PASS");
ssid.toCharArray(ssid_char, 20);
pass.toCharArray(pass_char, 20);
WiFi.begin(ssid_char, pass_char);
target_time = millis() + 10000;
while (millis() < target_time && WiFi.status() != WL_CONNECTED) {
led.setPixelColor(0, led.Color(0, 100, 0));
led.show();
delay(1000);
led.setPixelColor(0, led.Color(0, 0, 0));
led.show();
delay(1000);
}
if (WiFi.status() != WL_CONNECTED) {
WiFi.mode(WIFI_MODE_AP);
WiFi.softAP("clicker", "clcob5364");
WiFi.softAPIP();
}
// Get Companion Info
layer = prefs.getString("LAYER");
ip_address = prefs.getString("IPADDRESS");
// Send web page with input fields to client
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
if (request->hasParam("pass") && request->hasParam("ssid")) {
request->send_P(200, "text/html", index_html.c_str());
ssid = request->getParam("ssid")->value();
pass = request->getParam("pass")->value();
Serial.print("New Password is:\t");
Serial.println(pass);
Serial.print("New SSID is:\t");
Serial.println(ssid);
prefs.putString("SSID", ssid);
prefs.putString("PASS", pass);
Serial.println("Done");
} else if (request->hasParam("data")) {
ssid = prefs.getString("SSID");
pass = prefs.getString("PASS");
request->send(200, "text/html", "<!DOCTYPE HTML><html><head><title>ESP Clicker</title><meta name='viewport' content='width=device-width, initial-scale=1'></head><body><h1>Current WIFI Settings</h1><hr><br/>SSID: \"" + ssid + "\"<br/>Password: \"" + pass + "\"<br/><br/><br/><hr><button onclick=\"window.location.href='/';\">Back</button></body></html>");
} else if (request->hasParam("ipaddress")) {
request->send_P(200, "text/html", index_html.c_str());
ip_address = request->getParam("ipaddress")->value();
prefs.putString("IPADDRESS", ip_address);
} else if (request->hasParam("ipget")) {
ip_address = prefs.getString("IPADDRESS");
request->send(200, "text/html", "<!DOCTYPE HTML><html><head><title>ESP Clicker</title><meta name='viewport' content='width=device-width, initial-scale=1'></head><body><h1>Current IP Settings</h1><hr>Remote IP Address: \"" + ip_address + "\"<br/><br/><br/><hr><button onclick=\"window.location.href='/';\">Back</button></body></html>");
} else if (request->hasParam("layer")) {
request->send_P(200, "text/html", index_html.c_str());
layer = request->getParam("layer")->value();
prefs.putString("LAYER", layer);
} else if (request->hasParam("layerget")) {
layer = prefs.getString("LAYER");
request->send(200, "text/html", "<!DOCTYPE HTML><html><head><title>ESP Clicker</title><meta name='viewport' content='width=device-width, initial-scale=1'></head><body><h1>Current IP Settings</h1><hr>Remote Companion Layer: \"" + layer + "\"<br/><br/><br/><hr><button onclick=\"window.location.href='/';\">Back</button></body></html>");
} else if (request->hasParam("voltageget")) {
voltage = battery.voltage();
voltage = voltage / 1000;
Serial.println(voltage);
request->send(200, "text/html", "<!DOCTYPE HTML><html><head><title>ESP Clicker</title><meta name='viewport' content='width=device-width, initial-scale=1'></head><body><h1>Current voltage</h1><hr>\"" + String(voltage) + "\" Volts <br/>" + String(battery.level()) + "% Battery Percentage<br/><br/><br/><hr><button onclick=\"window.location.href='/';\">Back</button></body></html>");
} else if (request->hasParam("name")) {
name = request->getParam("name")->value();
index_html = index_html1 + name + index_html2;
prefs.putString("NAME", name);
request->send_P(200, "text/html", index_html.c_str());
} else if (request->hasParam("lazer")) {
lazer_button = request->getParam("lazer")->value().toInt();
prefs.putInt("LAZER_BUTTON", lazer_button);
request->send_P(200, "text/html", index_html.c_str());
} else {
request->send_P(200, "text/html", index_html.c_str());
}
index_html = index_html1 + name + index_html2;
});
server.begin();
}
// the loop function runs over and over again forever
void loop() {
lazer();
// Read port 0
if (digitalRead(BUTTON0)) {
Serial.println("Button 0");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/1/press");
waitfor();
}
// Read port 1
if (digitalRead(BUTTON1)) {
Serial.println("Button 1");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/2/press");
waitfor();
}
// Read port 2
if (digitalRead(BUTTON2)) {
Serial.println("Button 2");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/3/press");
waitfor();
}
// Read port 3
if (digitalRead(BUTTON3)) {
Serial.println("Button 3");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/4/press");
waitfor();
}
// Read port 4
if (digitalRead(BUTTON4)) {
Serial.println("Button 4");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/5/press");
waitfor();
}
// Read port 5
if (digitalRead(BUTTON5)) {
Serial.println("Button 5");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/6/press");
waitfor();
}
// Read port 6
if (digitalRead(BUTTON6)) {
Serial.println("Button 6");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/0/7/press");
waitfor();
}
// Read port 7
if (digitalRead(BUTTON7)) {
Serial.println("Button 7");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/1/1/press");
waitfor();
}
// Read port 8
if (digitalRead(BUTTON8)) {
Serial.println("Button 8");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/1/2/press");
waitfor();
}
// Read port 9
if (digitalRead(BUTTON9)) {
Serial.println("Button 9");
httpResponseCode = POSTRequest("http://" + ip_address + ":8000/api/location/" + layer + "/1/3/press");
waitfor();
}
voltage = battery.voltage();
voltage = voltage / 1000;
lazer();
if (voltage < 3.68) {
led.setPixelColor(0, led.Color(1, 0, 0));
} else if (!connected) {
led.setPixelColor(0, led.Color(1, 1, 1));
} else {
led.setPixelColor(0, led.Color(0, 1, 0));
}
led.show();
}
void waitfor() {
while (digitalRead(BUTTON0) || digitalRead(BUTTON1) || digitalRead(BUTTON2) || digitalRead(BUTTON3) || digitalRead(BUTTON4) || digitalRead(BUTTON5) || digitalRead(BUTTON6) || digitalRead(BUTTON7) || digitalRead(BUTTON8) || digitalRead(BUTTON9)) {
led.setPixelColor(0, led.Color(0, 0, 0));
led.show();
}
led.show();
if (httpResponseCode == 200) {
connected = true;
Serial.println(httpResponseCode);
} else {
connected = false;
Serial.println(httpResponseCode);
}
httpResponseCode = -1;
}
void lazer() {
if (lazer_button != -1) {
if (digitalRead(button[lazer_button])) {
led.setPixelColor(0, led.Color(255, 0, 0));
led.show();
digitalWrite(LAZER, HIGH);
while (digitalRead(button[lazer_button]))
;
digitalWrite(LAZER, LOW);
}
}
}
int GETRequest(String URL) {
int response;
HTTPClient http;
http.begin(URL.c_str());
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.setTimeout(5000);
response = http.GET();
http.end();
Serial.println(URL);
return response;
}
int POSTRequest(String URL) {
int response;
HTTPClient http;
http.begin(URL.c_str());
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.setTimeout(5000);
response = http.POST("");
http.end();
Serial.println(URL);
return response;
}
void bleclicker() {
bleKeyboard.setName("ESP Clicker");
bleKeyboard.begin();
bleKeyboard.setBatteryLevel(battery.level());
while (true) {
while (bleKeyboard.isConnected()) {
// Set LED Color
led.setPixelColor(0, led.Color(0, 0, 1));
led.show();
if (millis() > target_time) {
bleKeyboard.setBatteryLevel(battery.level());
Serial.println("battery update");
target_time = millis() + 60000;
}
// Read port 0
if (digitalRead(BUTTON0)) {
Serial.println("Button 0");
bleKeyboard.write(KEY_LEFT_ARROW);
waitfor();
}
// Read port 1
if (digitalRead(BUTTON1)) {
Serial.println("Button 1");
bleKeyboard.write(KEY_RIGHT_ARROW);
waitfor();
}
// Read port 2
if (digitalRead(BUTTON8)) {
Serial.println("Lazer");
led.setPixelColor(0, led.Color(255, 0, 0));
led.show();
digitalWrite(LAZER, HIGH);
while (digitalRead(BUTTON8))
;
digitalWrite(LAZER, LOW);
}
}
// Wait for a Second
led.setPixelColor(0, led.Color(0, 0, 100));
led.show();
delay(1000);
led.setPixelColor(0, led.Color(0, 0, 0));
led.show();
delay(1000);
}
}