Files
arduino-sony-minidisc-ir-re…/arduino-sony-minidisc-ir-remote.ino
T
2024-07-26 23:29:44 +02:00

448 lines
11 KiB
Arduino

/*
WebServer to use as replacement for Sony RM-D27M to control Sony MiniDisc decks.
Based on the the following sketches:
- SimpleWifiServer example
- ESP32/SD_Test
- IRremote/SendDemo
Circuit:
- LED attached to pin 13 (optional)
- IR Transmitter attached to pin 4 (connect to 5v or 3v3)
- SD-Module to load HTML and CSS from SD-card
Connect the SD card to the following pins:
SD Card | ESP32
------- | -----
3v3 | 3.3V
CS | 5
MOSI | 23
CLK | 18
MISO | 19
GND | GND
developed for the ESP32vn IoT Uni board 2024
*/
//-----------------------------------------
// Arduino Web Server using AJAX
// HTML code of webpage is stored on SD card
//-----------------------------------------
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <IRremote.hpp>
#include "secrets.h"
#include "defines.h"
#include "initfunctions.h"
//------------------------------------------------
typedef struct
{
char *key;
uint8_t value;
} record_type;
record_type upperCaseAlphaChar[26] = {
{"A", 0x1D},
{"B", 0x1E},
{"C", 0x1F},
{"D", 0x1B},
{"E", 0x1A},
{"F", 0x0},
{"G", 0x1},
{"H", 0x2},
{"I", 0x3},
{"J", 0x4},
{"K", 0x5},
{"L", 0x6},
{"M", 0x7},
{"N", 0x8},
{"O", 0x9},
{"P", 0x40},
{"Q", 0x41},
{"R", 0x42},
{"S", 0x43},
{"T", 0x44},
{"U", 0x45},
{"V", 0x46},
{"W", 0x47},
{"X", 0x48},
{"Y", 0x49},
{"Z", 0x4A}};
record_type lowerCaseAlphaChar[26] = {
{"a", 0x1D},
{"b", 0x1E},
{"c", 0x1F},
{"d", 0x1B},
{"e", 0x1A},
{"f", 0x0},
{"g", 0x1},
{"h", 0x2},
{"i", 0x3},
{"j", 0x4},
{"k", 0x5},
{"l", 0x6},
{"m", 0x7},
{"n", 0x8},
{"o", 0x9},
{"p", 0x40},
{"q", 0x41},
{"r", 0x42},
{"s", 0x43},
{"t", 0x44},
{"u", 0x45},
{"v", 0x46},
{"w", 0x47},
{"x", 0x48},
{"y", 0x49},
{"z", 0x4A}};
record_type numberChar[10] = {
{"1", 0x0},
{"2", 0x1},
{"3", 0x2},
{"4", 0x3},
{"5", 0x4},
{"6", 0x5},
{"7", 0x6},
{"8", 0x7},
{"9", 0x8},
{"0", 0x9}};
record_type specialChar[8] = {
{"-", 0x4B},
{".", 0x4D},
{",", 0x4E},
{"/", 0xA},
{"?", 0x26},
{"!", 0x27},
{"(", 0x33},
{")", 0x34}};
bool isLowercase = false;
bool isNumber = false;
//! Vielleicht smarter immer den vorherigen zu setzen und damit zu vergleichen
bool wasLowercase = false;
bool wasNumber = false;
//------------------------------------------------
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
const char *PARAM_MESSAGE = "message";
void notFound(AsyncWebServerRequest *request)
{
request->send(404, "text/plain", "Not found");
}
//------------------------------------------------
//--------------- IR Functions -------------------
void initIR()
{
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println();
Serial.print(F("Send IR signals at pin "));
Serial.println(IR_SEND_PIN);
}
void sendButton12(int command)
{
Serial.print("sendButton12 command: ");
Serial.println(command);
Serial.flush();
IrSender.sendSony(0xF, command, 2, 12);
}
void sendButton20(int command)
{
Serial.print(F("Send Sony/SIRCS with 7 command and 13 address bits: "));
Serial.println(command);
Serial.flush();
IrSender.sendSony(0xF & 0x1FFF, command & 0x7F, 2, SIRCS_20_PROTOCOL);
}
void sendCommand12(String commandString)
{
if (commandString == "POWER")
sendButton12(POWER);
if (commandString == "PLAY")
sendButton12(PLAY);
if (commandString == "PAUSE")
sendButton12(PAUSE);
if (commandString == "STOP")
sendButton12(STOP);
if (commandString == "PREV")
sendButton12(PREV);
if (commandString == "NEXT")
sendButton12(NEXT);
else
{
Serial.println("wrong command!");
}
}
//! Ich brauche eine Funktion, die den vorherigen und den folgenden char prüft und checked, ob der lowercase, oder num ist und dann entsprechend den Modus umschaltet.
//! Ich brauche eine Funktion, die den char mit einem IR command vergleicht und den IrSender.sendSony() ausführt.
void sendCommand20(String commandString)
{
if (commandString == "Q")
sendButton12(keyQ);
if (commandString == "W")
sendButton12(keyW);
if (commandString == "E")
sendButton12(keyE);
if (commandString == "R")
sendButton12(keyR);
if (commandString == "T")
sendButton12(keyT);
if (commandString == "Z")
sendButton12(keyZ);
else
{
Serial.println("wrong command!");
}
}
//! void findCommandAndSend(String char)
//! { find char in Array and use value to send command }
void caseToggleLow()
{
if (wasNumber == true)
Serial.println("toggle to char");
wasNumber = false;
if (wasLowercase == false)
Serial.println("toggle case low");
if (wasLowercase == true)
Serial.println("no toggle");
}
void caseToggleUp()
{
if (wasNumber == true)
Serial.println("toggle to char");
wasNumber = false;
if (wasLowercase == true)
Serial.println("toggle case up");
if (wasLowercase == false)
Serial.println("no toggle");
}
void toggleDigit()
{
if (wasNumber == true)
Serial.println("no toggle");
if (wasNumber == false)
Serial.println("toggle to digit");
wasNumber = true;
}
void finalizeTrack()
{
Serial.println("Finalize track");
}
void nameSingleTrack(String titlestring)
{
Serial.print("track name: ");
Serial.println(titlestring);
//! Brauche ich den null terminator?
int str_len = titlestring.length() + 1; // Length (with one extra character for the null terminator)
Serial.print("string length: ");
Serial.println(str_len);
char char_array[str_len]; // Prepare the character array (the buffer)
titlestring.toCharArray(char_array, str_len); // Copy it over
for (int i = 0; i < str_len; i++) // Loop over array
{
int s = char_array[i];
//! Hier müssen verschiedene Sachen getestet werden:
//! Ist das Array-Ende erreicht? Ist der case ein anderer als vom vorigen char? Prüft aktuelle char und entscheidet, welches Command gesendet wird
//! Wie kann ich das in eigene Funktionen verpacken?
if (i == str_len - 1)
{
Serial.println("End of line.");
finalizeTrack();
}
else
{
Serial.println(i);
Serial.println("char: ");
Serial.println(char_array[i]);
// Test if char is a lowerCase letter
if (isLowerCase(char_array[i]))
{
Serial.println("The character is lower case");
caseToggleLow();
wasLowercase = true;
wasNumber = false;
}
// Test if char is a upperCase letter
if (isUpperCase(char_array[i]))
{
Serial.println("The character is upper case");
caseToggleUp();
wasLowercase = false;
wasNumber = false;
}
// Test if char is a digit
if (isDigit(char_array[i]))
{
Serial.println("The character is digit");
toggleDigit();
wasNumber = true;
}
// Test if char is special char
if (isPunct(char_array[i]))
{
Serial.println("The character is special char");
}
// Test if char is a space
if (isSpace(char_array[i]))
{
Serial.println("The character is a space");
}
}
}
}
void nameAllTracks(String message)
{
Serial.print("track list: ");
Serial.println(message);
// split into array of strings after each line break
// use nameSingleTrack with each track
}
//------------------------------------------------
//-------------------- Setup ---------------------
void setup()
{
Serial.begin(115200);
Serial.print("numberChar[1].value: ");
Serial.println(numberChar[1].value);
Serial.print("numberChar[1].key: ");
Serial.println(numberChar[1].key);
Serial.print("specialChar[0].value: ");
Serial.println(specialChar[0].value);
Serial.print("specialChar[0].key: ");
Serial.println(specialChar[0].key);
Serial.print("specialChar[2].value: ");
Serial.println(specialChar[2].value);
Serial.print("specialChar[7].value: ");
Serial.println(specialChar[7].value);
Serial.print("specialChar[7].key: ");
Serial.println(specialChar[7].key);
initWiFi();
initSDCard();
pinMode(LED_PIN, OUTPUT); // set the LED pin mode
initIR();
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(SD, "/index.html", "text/html"); });
server.serveStatic("/", SD, "/");
// Send a POST request to <IP>/api/control-led with a form field message set to <message>
server.on("/api/control-led", HTTP_POST, [](AsyncWebServerRequest *request)
{
String message;
if (request->hasParam("led", true)) {
message = request->getParam("led", true)->value();
if (message == "1")
digitalWrite(LED_PIN, HIGH);
if (message == "0")
digitalWrite(LED_PIN, LOW);
} else {
message = "No message sent";
}
request->send(SD, "/index.html", "text/html"); });
// Send a POST request to <IP>/api/gettext with a form field message set to <message>
server.on("/api/gettracklist", HTTP_POST, [](AsyncWebServerRequest *request)
{
String message;
if (request->hasParam("tracklist", true)) {
message = request->getParam("tracklist", true)->value();
//Serial.println(message);
nameAllTracks(message);
} else {
message = "No message sent";
}
request->send(SD, "/index.html", "text/html"); });
// Send a GET request to <IP>/api/gettextinput?message=<message>
server.on("/api/gettrack", HTTP_GET, [](AsyncWebServerRequest *request)
{
String message;
if (request->hasParam("singletrack"))
{
message = request->getParam("singletrack")->value();
//Serial.println(message);
nameSingleTrack(message);
}
else
{
message = "No message sent";
}
request->send(SD, "/index.html", "text/html"); });
// Send a POST request to <IP>/api/control-deck with a form field message set to <message>
server.on("/api/control-deck", HTTP_POST, [](AsyncWebServerRequest *request)
{
String message;
if (request->hasParam("control", true)) {
message = request->getParam("control", true)->value();
sendCommand12(message);
} else {
message = "No message sent";
}
request->send(SD, "/index.html", "text/html"); });
// Send a POST request to <IP>/api/keyboard-input with a form field message set to <message>
server.on("/api/keyboard-input", HTTP_POST, [](AsyncWebServerRequest *request)
{
String message;
if (request->hasParam("key", true)) {
message = request->getParam("key", true)->value();
sendCommand20(message);
} else {
message = "No message sent";
}
request->send(SD, "/index.html", "text/html"); });
server.onNotFound(notFound);
server.begin();
}
void loop()
{
}