OMOTE/Platformio/src/applicationInternal/commandHandler.cpp
2024-05-10 12:33:35 +02:00

292 lines
13 KiB
C++

#include <string>
#include <list>
#include <sstream>
#include <algorithm>
#include <stdexcept>
#include "applicationInternal/commandHandler.h"
#include "applicationInternal/scenes/sceneHandler.h"
#include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/omote_log.h"
#include "devices/misc/device_specialCommands.h"
// show WiFi status
#include "applicationInternal/gui/guiBase.h"
// show received IR and MQTT messages
#include "guis/gui_irReceiver.h"
uint16_t COMMAND_UNKNOWN;
uint16_t KEYBOARD_DUMMY_UP ; //"Keyboard_dummy_up"
uint16_t KEYBOARD_DUMMY_DOWN ; //"Keyboard_dummy_down"
uint16_t KEYBOARD_DUMMY_RIGHT ; //"Keyboard_dummy_right"
uint16_t KEYBOARD_DUMMY_LEFT ; //"Keyboard_dummy_left"
uint16_t KEYBOARD_DUMMY_SELECT ; //"Keyboard_dummy_select"
uint16_t KEYBOARD_DUMMY_SENDSTRING ; //"Keyboard_dummy_sendstring"
uint16_t KEYBOARD_DUMMY_BACK ; //"Keyboard_dummy_back"
uint16_t KEYBOARD_DUMMY_HOME ; //"Keyboard_dummy_home"
uint16_t KEYBOARD_DUMMY_MENU ; //"Keyboard_dummy_menu"
uint16_t KEYBOARD_DUMMY_SCAN_PREVIOUS_TRACK ; //"Keyboard_dummy_scan_previous_track"
uint16_t KEYBOARD_DUMMY_REWIND_LONG ; //"Keyboard_dummy_rewind_long"
uint16_t KEYBOARD_DUMMY_REWIND ; //"Keyboard_dummy_rewind"
uint16_t KEYBOARD_DUMMY_PLAYPAUSE ; //"Keyboard_dummy_playpause"
uint16_t KEYBOARD_DUMMY_FASTFORWARD ; //"Keyboard_dummy_fastforward"
uint16_t KEYBOARD_DUMMY_FASTFORWARD_LONG ; //"Keyboard_dummy_fastforward_long"
uint16_t KEYBOARD_DUMMY_SCAN_NEXT_TRACK ; //"Keyboard_dummy_scan_next_track"
uint16_t KEYBOARD_DUMMY_MUTE ; //"Keyboard_dummy_mute"
uint16_t KEYBOARD_DUMMY_VOLUME_INCREMENT ; //"Keyboard_dummy_volume_increment"
uint16_t KEYBOARD_DUMMY_VOLUME_DECREMENT ; //"Keyboard_dummy_volume_decrement"
uint16_t KEYBOARD_UP ; //PPCAT(KEYBOARD_PREFIX, UP)
uint16_t KEYBOARD_DOWN ; //PPCAT(KEYBOARD_PREFIX, DOWN)
uint16_t KEYBOARD_RIGHT ; //PPCAT(KEYBOARD_PREFIX, RIGHT)
uint16_t KEYBOARD_LEFT ; //PPCAT(KEYBOARD_PREFIX, LEFT)
uint16_t KEYBOARD_SELECT ; //PPCAT(KEYBOARD_PREFIX, SELECT)
uint16_t KEYBOARD_SENDSTRING ; //PPCAT(KEYBOARD_PREFIX, SENDSTRING)
uint16_t KEYBOARD_BACK ; //PPCAT(KEYBOARD_PREFIX, BACK)
uint16_t KEYBOARD_HOME ; //PPCAT(KEYBOARD_PREFIX, HOME)
uint16_t KEYBOARD_MENU ; //PPCAT(KEYBOARD_PREFIX, MENU)
uint16_t KEYBOARD_SCAN_PREVIOUS_TRACK ; //PPCAT(KEYBOARD_PREFIX, SCAN_PREVIOUS_TRACK)
uint16_t KEYBOARD_REWIND_LONG ; //PPCAT(KEYBOARD_PREFIX, REWIND_LONG)
uint16_t KEYBOARD_REWIND ; //PPCAT(KEYBOARD_PREFIX, REWIND)
uint16_t KEYBOARD_PLAYPAUSE ; //PPCAT(KEYBOARD_PREFIX, PLAYPAUSE)
uint16_t KEYBOARD_FASTFORWARD ; //PPCAT(KEYBOARD_PREFIX, FASTFORWARD)
uint16_t KEYBOARD_FASTFORWARD_LONG ; //PPCAT(KEYBOARD_PREFIX, FASTFORWARD_LONG)
uint16_t KEYBOARD_SCAN_NEXT_TRACK ; //PPCAT(KEYBOARD_PREFIX, SCAN_NEXT_TRACK)
uint16_t KEYBOARD_MUTE ; //PPCAT(KEYBOARD_PREFIX, MUTE)
uint16_t KEYBOARD_VOLUME_INCREMENT ; //PPCAT(KEYBOARD_PREFIX, VOLUME_INCREMENT)
uint16_t KEYBOARD_VOLUME_DECREMENT ; //PPCAT(KEYBOARD_PREFIX, VOLUME_DECREMENT)
std::map<uint16_t, commandData> commands;
uint16_t uniqueCommandID = 0;
// we don't yet have a command id
void register_command(uint16_t *command, commandData aCommandData) {
*command = uniqueCommandID;
uniqueCommandID++;
commands[*command] = aCommandData;
}
// we already have a command id. Only used by BLE keyboard
void register_command_withID(uint16_t command, commandData aCommandData) {
commands[command] = aCommandData;
}
// only get a unique ID. used by KEYBOARD_DUMMY, COMMAND_UNKNOWN and BLE keyboard
void get_uniqueCommandID(uint16_t *command) {
*command = uniqueCommandID;
uniqueCommandID++;
}
void register_keyboardCommands() {
get_uniqueCommandID(&KEYBOARD_DUMMY_UP );
get_uniqueCommandID(&KEYBOARD_DUMMY_DOWN );
get_uniqueCommandID(&KEYBOARD_DUMMY_RIGHT );
get_uniqueCommandID(&KEYBOARD_DUMMY_LEFT );
get_uniqueCommandID(&KEYBOARD_DUMMY_SELECT );
get_uniqueCommandID(&KEYBOARD_DUMMY_SENDSTRING );
get_uniqueCommandID(&KEYBOARD_DUMMY_BACK );
get_uniqueCommandID(&KEYBOARD_DUMMY_HOME );
get_uniqueCommandID(&KEYBOARD_DUMMY_MENU );
get_uniqueCommandID(&KEYBOARD_DUMMY_SCAN_PREVIOUS_TRACK );
get_uniqueCommandID(&KEYBOARD_DUMMY_REWIND_LONG );
get_uniqueCommandID(&KEYBOARD_DUMMY_REWIND );
get_uniqueCommandID(&KEYBOARD_DUMMY_PLAYPAUSE );
get_uniqueCommandID(&KEYBOARD_DUMMY_FASTFORWARD );
get_uniqueCommandID(&KEYBOARD_DUMMY_FASTFORWARD_LONG );
get_uniqueCommandID(&KEYBOARD_DUMMY_SCAN_NEXT_TRACK );
get_uniqueCommandID(&KEYBOARD_DUMMY_MUTE );
get_uniqueCommandID(&KEYBOARD_DUMMY_VOLUME_INCREMENT );
get_uniqueCommandID(&KEYBOARD_DUMMY_VOLUME_DECREMENT );
#if (ENABLE_KEYBOARD_BLE == 1)
KEYBOARD_UP = KEYBOARD_BLE_UP;
KEYBOARD_DOWN = KEYBOARD_BLE_DOWN;
KEYBOARD_RIGHT = KEYBOARD_BLE_RIGHT;
KEYBOARD_LEFT = KEYBOARD_BLE_LEFT;
KEYBOARD_SELECT = KEYBOARD_BLE_SELECT;
KEYBOARD_SENDSTRING = KEYBOARD_BLE_SENDSTRING;
KEYBOARD_BACK = KEYBOARD_BLE_BACK;
KEYBOARD_HOME = KEYBOARD_BLE_HOME;
KEYBOARD_MENU = KEYBOARD_BLE_MENU;
KEYBOARD_SCAN_PREVIOUS_TRACK = KEYBOARD_BLE_SCAN_PREVIOUS_TRACK;
KEYBOARD_REWIND_LONG = KEYBOARD_BLE_REWIND_LONG;
KEYBOARD_REWIND = KEYBOARD_BLE_REWIND;
KEYBOARD_PLAYPAUSE = KEYBOARD_BLE_PLAYPAUSE;
KEYBOARD_FASTFORWARD = KEYBOARD_BLE_FASTFORWARD;
KEYBOARD_FASTFORWARD_LONG = KEYBOARD_BLE_FASTFORWARD_LONG;
KEYBOARD_SCAN_NEXT_TRACK = KEYBOARD_BLE_SCAN_NEXT_TRACK;
KEYBOARD_MUTE = KEYBOARD_BLE_MUTE;
KEYBOARD_VOLUME_INCREMENT = KEYBOARD_BLE_VOLUME_INCREMENT;
KEYBOARD_VOLUME_DECREMENT = KEYBOARD_BLE_VOLUME_DECREMENT;
#elif (ENABLE_KEYBOARD_MQTT == 1)
KEYBOARD_UP = KEYBOARD_MQTT_UP;
KEYBOARD_DOWN = KEYBOARD_MQTT_DOWN;
KEYBOARD_RIGHT = KEYBOARD_MQTT_RIGHT;
KEYBOARD_LEFT = KEYBOARD_MQTT_LEFT;
KEYBOARD_SELECT = KEYBOARD_MQTT_SELECT;
KEYBOARD_SENDSTRING = KEYBOARD_MQTT_SENDSTRING;
KEYBOARD_BACK = KEYBOARD_MQTT_BACK;
KEYBOARD_HOME = KEYBOARD_MQTT_HOME;
KEYBOARD_MENU = KEYBOARD_MQTT_MENU;
KEYBOARD_SCAN_PREVIOUS_TRACK = KEYBOARD_MQTT_SCAN_PREVIOUS_TRACK;
KEYBOARD_REWIND_LONG = KEYBOARD_MQTT_REWIND_LONG;
KEYBOARD_REWIND = KEYBOARD_MQTT_REWIND;
KEYBOARD_PLAYPAUSE = KEYBOARD_MQTT_PLAYPAUSE;
KEYBOARD_FASTFORWARD = KEYBOARD_MQTT_FASTFORWARD;
KEYBOARD_FASTFORWARD_LONG = KEYBOARD_MQTT_FASTFORWARD_LONG;
KEYBOARD_SCAN_NEXT_TRACK = KEYBOARD_MQTT_SCAN_NEXT_TRACK;
KEYBOARD_MUTE = KEYBOARD_MQTT_MUTE;
KEYBOARD_VOLUME_INCREMENT = KEYBOARD_MQTT_VOLUME_INCREMENT;
KEYBOARD_VOLUME_DECREMENT = KEYBOARD_MQTT_VOLUME_DECREMENT;
#else
// Of course keyboard commands will not work if neither BLE nor MQTT keyboard is enabled, but at least code will compile.
// But you have to change keys.cpp, gui_numpad.cpp and commandHandler.cpp where keyboard commands are used so that a command can be executed successfully.
// Search for "executeCommand(Key" to find them.
KEYBOARD_UP = KEYBOARD_DUMMY_UP;
KEYBOARD_DOWN = KEYBOARD_DUMMY_DOWN;
KEYBOARD_RIGHT = KEYBOARD_DUMMY_RIGHT;
KEYBOARD_LEFT = KEYBOARD_DUMMY_LEFT;
KEYBOARD_SELECT = KEYBOARD_DUMMY_SELECT;
KEYBOARD_SENDSTRING = KEYBOARD_DUMMY_SENDSTRING;
KEYBOARD_BACK = KEYBOARD_DUMMY_BACK;
KEYBOARD_HOME = KEYBOARD_DUMMY_HOME;
KEYBOARD_MENU = KEYBOARD_DUMMY_MENU;
KEYBOARD_SCAN_PREVIOUS_TRACK = KEYBOARD_DUMMY_SCAN_PREVIOUS_TRACK;
KEYBOARD_REWIND_LONG = KEYBOARD_DUMMY_REWIND_LONG;
KEYBOARD_REWIND = KEYBOARD_DUMMY_REWIND;
KEYBOARD_PLAYPAUSE = KEYBOARD_DUMMY_PLAYPAUSE;
KEYBOARD_FASTFORWARD = KEYBOARD_DUMMY_FASTFORWARD;
KEYBOARD_FASTFORWARD_LONG = KEYBOARD_DUMMY_FASTFORWARD_LONG;
KEYBOARD_SCAN_NEXT_TRACK = KEYBOARD_DUMMY_SCAN_NEXT_TRACK;
KEYBOARD_MUTE = KEYBOARD_DUMMY_MUTE;
KEYBOARD_VOLUME_INCREMENT = KEYBOARD_DUMMY_VOLUME_INCREMENT;
KEYBOARD_VOLUME_DECREMENT = KEYBOARD_DUMMY_VOLUME_DECREMENT;
#endif
}
commandData makeCommandData(commandHandlers a, std::list<std::string> b) {
commandData c = {a, b};
return c;
}
std::string convertStringListToString(std::list<std::string> listOfStrings) {
std::string result;
for(const auto &word : listOfStrings) {
result += word + ",";
}
return result;
}
void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload = "") {
switch (commandData.commandHandler) {
case IR: {
omote_log_v(" generic IR, payloads %s\r\n", convertStringListToString(commandData.commandPayloads).c_str());
// we received a comma separated list of strings
// the first string is the IR protocol, the second is the payload to be sent
std::list<std::string>::iterator it = commandData.commandPayloads.begin();
// get protocol and erase first element in list
std::string protocol = *it;
it = commandData.commandPayloads.erase(it);
omote_log_v(" protocol %s, payload %s\r\n", protocol.c_str(), convertStringListToString(commandData.commandPayloads).c_str());
sendIRcode((IRprotocols)std::stoi(protocol), commandData.commandPayloads, additionalPayload);
break;
}
#if (ENABLE_WIFI_AND_MQTT == 1)
case MQTT: {
auto current = commandData.commandPayloads.begin();
std::string topic = *current;
std::string payload;
if (additionalPayload == "") {
current = std::next(current, 1);
payload = *current;
} else {
payload = additionalPayload;
}
omote_log_d("execute: will send MQTT, topic '%s', payload '%s'\r\n", topic.c_str(), payload.c_str());
publishMQTTMessage(topic.c_str(), payload.c_str());
break;
}
#endif
#if (ENABLE_KEYBOARD_BLE == 1)
case BLE_KEYBOARD: {
// the real command for the BLE keyboard is the first element in payload
auto current = commandData.commandPayloads.begin();
uint16_t command = std::stoi(*current);
std::string payload = "";
if (additionalPayload != "") {
payload = additionalPayload;
}
omote_log_d("execute: will send BLE keyboard command, command '%u', payload '%s'\r\n", command, payload.c_str());
keyboard_ble_executeCommand(command, payload);
break;
}
#endif
case SCENE: {
// let the sceneHandler do the scene stuff
omote_log_d("execute: will send scene command to the sceneHandler\r\n");
handleScene(command, commandData, additionalPayload);
break;
}
case GUI: {
// let the sceneHandler find and show the gui
omote_log_d("execute: will send gui command to the sceneHandler\r\n");
handleGUI(command, commandData, additionalPayload);
break;
}
case SPECIAL: {
if (command == MY_SPECIAL_COMMAND) {
// do your special command here
omote_log_d("execute: could execute a special command here, if you define one\r\n");
}
break;
}
}
}
void executeCommand(uint16_t command, std::string additionalPayload) {
try {
if (commands.count(command) > 0) {
omote_log_d("command: will execute command '%u' with additionalPayload '%s'\r\n", command, additionalPayload.c_str());
executeCommandWithData(command, commands.at(command), additionalPayload);
} else {
omote_log_w("command: command '%u' not found\r\n", command);
}
}
catch (const std::out_of_range& oor) {
omote_log_e("executeCommand: internal error, command not registered\r\n");
}
}
void receiveNewIRmessage_cb(std::string message) {
showNewIRmessage(message);
}
#if (ENABLE_WIFI_AND_MQTT == 1)
void receiveWiFiConnected_cb(bool connected) {
// show status in header
showWiFiConnected(connected);
if (connected) {
// Here you could add sending a MQTT message. This message could be recognized by your home automation software.
// When receiving this message, your home automation software could send the states of the smart home devices known to OMOTE.
// With that, OMOTE could show on startup the correct status of the smart home devices.
//
// Remark: in your home automation software, maybe add a short delay (e.g. 100-200 ms) between receiving this message and sending out the status of the smart home devices.
// WiFi connection could be already available, but MQTT connection could be not completely ready. Just try what works for you.
// executeCommand(TRIGGER_UPDATE_OF_OMOTE_SMART_HOME_DEVICES);
}
}
void receiveMQTTmessage_cb(std::string topic, std::string payload) {
showMQTTmessage(topic, payload);
}
#endif