Modular approach - first version for main branch (#60)
* first version of "modular-approach" * changed keyboard commands for HOME and BACK * Update README.md * only some typos in comments * readability * comment for what the mqtt keyboard is used * removed numbering of tab variables. not needed anymore * changed the default keyboard from "´mqtt keyboard" to "BLE keyboard" * updated to latest version of keypad library from Github, changes for inverted logic are explicitely marked * added comment for key repeatModes * added comment for MQTT keyboard * setting timout via GUI now works, not only dropdown without functionality * BLE indicator added; separation of BLE/WiFi activation from activation of devices using it * report battery level to BLE device * Dynamic keyboard commands, so you can safely deactivate BLE and/or WiFi and not break the example code * reorganized files into folders * moved lv_conf.h into the gui folder * added devices for appleTV and smarthome * assets.c broken up and placed them where they are used * added support for IR RC5 * reorganization of files and folder * added comment * renamed assets files * introduction of gui_registry * removed unnecessary functions from sleep.h * use gui_registry.h only once * some files renamed for better understandability * minor renaming * some more renaming * check if WiFi label was instantiated before using it * introduction of a scene registry * save prefs directly after timeout is changed * renaming of preferencesStorage * comment added * only readability * detailled definition of key layout for the diferrent scenes * made code compile for "device_smarthome" when WiFi is deactivated * fixed access violation when no scene was active * added support for IR DENON commands * increased lvgl heap from 32K to 48K
This commit is contained in:
parent
d97d263620
commit
7ba79d5c92
79 changed files with 4884 additions and 1156 deletions
2
Platformio/.gitignore
vendored
2
Platformio/.gitignore
vendored
|
@ -1,5 +1,7 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/extensions.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
src/secrets_override.h
|
||||
|
|
3
Platformio/.vscode/settings.json
vendored
3
Platformio/.vscode/settings.json
vendored
|
@ -2,7 +2,8 @@
|
|||
"cmake.configureOnOpen": false,
|
||||
"files.associations": {
|
||||
"random": "cpp",
|
||||
"array": "cpp"
|
||||
"array": "cpp",
|
||||
"lvgl.h": "c"
|
||||
},
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO"
|
||||
}
|
1
Platformio/lib/ESP32-BLE-Keyboard/.piopm
Normal file
1
Platformio/lib/ESP32-BLE-Keyboard/.piopm
Normal file
|
@ -0,0 +1 @@
|
|||
{"type": "library", "name": "ESP32 BLE Keyboard", "version": "0.3.2", "spec": {"owner": "t-vk", "id": 6749, "name": "ESP32 BLE Keyboard", "requirements": null, "uri": null}}
|
552
Platformio/lib/ESP32-BLE-Keyboard/BleKeyboard.cpp
Normal file
552
Platformio/lib/ESP32-BLE-Keyboard/BleKeyboard.cpp
Normal file
|
@ -0,0 +1,552 @@
|
|||
#include "BleKeyboard.h"
|
||||
|
||||
#if defined(USE_NIMBLE)
|
||||
#include <NimBLEDevice.h>
|
||||
#include <NimBLEServer.h>
|
||||
#include <NimBLEUtils.h>
|
||||
#include <NimBLEHIDDevice.h>
|
||||
#else
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEUtils.h>
|
||||
#include <BLEServer.h>
|
||||
#include "BLE2902.h"
|
||||
#include "BLEHIDDevice.h"
|
||||
#endif // USE_NIMBLE
|
||||
#include "HIDTypes.h"
|
||||
#include <driver/adc.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
#if defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||
#include "esp32-hal-log.h"
|
||||
#define LOG_TAG ""
|
||||
#else
|
||||
#include "esp_log.h"
|
||||
static const char* LOG_TAG = "BLEDevice";
|
||||
#endif
|
||||
|
||||
|
||||
// Report IDs:
|
||||
#define KEYBOARD_ID 0x01
|
||||
#define MEDIA_KEYS_ID 0x02
|
||||
|
||||
static const uint8_t _hidReportDescriptor[] = {
|
||||
USAGE_PAGE(1), 0x01, // USAGE_PAGE (Generic Desktop Ctrls)
|
||||
USAGE(1), 0x06, // USAGE (Keyboard)
|
||||
COLLECTION(1), 0x01, // COLLECTION (Application)
|
||||
// ------------------------------------------------- Keyboard
|
||||
REPORT_ID(1), KEYBOARD_ID, // REPORT_ID (1)
|
||||
USAGE_PAGE(1), 0x07, // USAGE_PAGE (Kbrd/Keypad)
|
||||
USAGE_MINIMUM(1), 0xE0, // USAGE_MINIMUM (0xE0)
|
||||
USAGE_MAXIMUM(1), 0xE7, // USAGE_MAXIMUM (0xE7)
|
||||
LOGICAL_MINIMUM(1), 0x00, // LOGICAL_MINIMUM (0)
|
||||
LOGICAL_MAXIMUM(1), 0x01, // Logical Maximum (1)
|
||||
REPORT_SIZE(1), 0x01, // REPORT_SIZE (1)
|
||||
REPORT_COUNT(1), 0x08, // REPORT_COUNT (8)
|
||||
HIDINPUT(1), 0x02, // INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
REPORT_COUNT(1), 0x01, // REPORT_COUNT (1) ; 1 byte (Reserved)
|
||||
REPORT_SIZE(1), 0x08, // REPORT_SIZE (8)
|
||||
HIDINPUT(1), 0x01, // INPUT (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
REPORT_COUNT(1), 0x05, // REPORT_COUNT (5) ; 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana)
|
||||
REPORT_SIZE(1), 0x01, // REPORT_SIZE (1)
|
||||
USAGE_PAGE(1), 0x08, // USAGE_PAGE (LEDs)
|
||||
USAGE_MINIMUM(1), 0x01, // USAGE_MINIMUM (0x01) ; Num Lock
|
||||
USAGE_MAXIMUM(1), 0x05, // USAGE_MAXIMUM (0x05) ; Kana
|
||||
HIDOUTPUT(1), 0x02, // OUTPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
REPORT_COUNT(1), 0x01, // REPORT_COUNT (1) ; 3 bits (Padding)
|
||||
REPORT_SIZE(1), 0x03, // REPORT_SIZE (3)
|
||||
HIDOUTPUT(1), 0x01, // OUTPUT (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
REPORT_COUNT(1), 0x06, // REPORT_COUNT (6) ; 6 bytes (Keys)
|
||||
REPORT_SIZE(1), 0x08, // REPORT_SIZE(8)
|
||||
LOGICAL_MINIMUM(1), 0x00, // LOGICAL_MINIMUM(0)
|
||||
LOGICAL_MAXIMUM(1), 0x65, // LOGICAL_MAXIMUM(0x65) ; 101 keys
|
||||
USAGE_PAGE(1), 0x07, // USAGE_PAGE (Kbrd/Keypad)
|
||||
USAGE_MINIMUM(1), 0x00, // USAGE_MINIMUM (0)
|
||||
USAGE_MAXIMUM(1), 0x65, // USAGE_MAXIMUM (0x65)
|
||||
HIDINPUT(1), 0x00, // INPUT (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
END_COLLECTION(0), // END_COLLECTION
|
||||
// ------------------------------------------------- Media Keys
|
||||
USAGE_PAGE(1), 0x0C, // USAGE_PAGE (Consumer)
|
||||
USAGE(1), 0x01, // USAGE (Consumer Control)
|
||||
COLLECTION(1), 0x01, // COLLECTION (Application)
|
||||
REPORT_ID(1), MEDIA_KEYS_ID, // REPORT_ID (3)
|
||||
USAGE_PAGE(1), 0x0C, // USAGE_PAGE (Consumer)
|
||||
LOGICAL_MINIMUM(1), 0x00, // LOGICAL_MINIMUM (0)
|
||||
LOGICAL_MAXIMUM(1), 0x01, // LOGICAL_MAXIMUM (1)
|
||||
REPORT_SIZE(1), 0x01, // REPORT_SIZE (1)
|
||||
REPORT_COUNT(1), 0x10, // REPORT_COUNT (16)
|
||||
USAGE(1), 0xB5, // USAGE (Scan Next Track) ; bit 0: 1
|
||||
USAGE(1), 0xB6, // USAGE (Scan Previous Track) ; bit 1: 2
|
||||
USAGE(1), 0xB7, // USAGE (Stop) ; bit 2: 4
|
||||
USAGE(1), 0xCD, // USAGE (Play/Pause) ; bit 3: 8
|
||||
USAGE(1), 0xE2, // USAGE (Mute) ; bit 4: 16
|
||||
USAGE(1), 0xE9, // USAGE (Volume Increment) ; bit 5: 32
|
||||
USAGE(1), 0xEA, // USAGE (Volume Decrement) ; bit 6: 64
|
||||
USAGE(2), 0x23, 0x02, // Usage (WWW Home) ; bit 7: 128
|
||||
USAGE(2), 0x94, 0x01, // Usage (My Computer) ; bit 0: 1
|
||||
// original from BLE-Keyboard
|
||||
// USAGE(2), 0x92, 0x01, // Usage (Calculator) ; bit 1: 2
|
||||
// changed for usage in OMOTE
|
||||
USAGE(1), 0xB3, // USAGE (Fast Forward); bit 1: 2
|
||||
USAGE(2), 0x2A, 0x02, // Usage (WWW fav) ; bit 2: 4
|
||||
USAGE(2), 0x21, 0x02, // Usage (WWW search) ; bit 3: 8
|
||||
USAGE(2), 0x26, 0x02, // Usage (WWW stop) ; bit 4: 16
|
||||
USAGE(2), 0x24, 0x02, // Usage (WWW back) ; bit 5: 32
|
||||
USAGE(2), 0x83, 0x01, // Usage (Media sel) ; bit 6: 64
|
||||
// original from BLE-Keyboard
|
||||
// USAGE(2), 0x8A, 0x01, // Usage (Mail) ; bit 7: 128
|
||||
// changed for usage in OMOTE
|
||||
USAGE(1), 0xB4, // USAGE (Rewind) ; bit 7: 128
|
||||
HIDINPUT(1), 0x02, // INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
END_COLLECTION(0) // END_COLLECTION
|
||||
};
|
||||
|
||||
BleKeyboard::BleKeyboard(std::string deviceName, std::string deviceManufacturer, uint8_t batteryLevel)
|
||||
: hid(0)
|
||||
, deviceName(std::string(deviceName).substr(0, 15))
|
||||
, deviceManufacturer(std::string(deviceManufacturer).substr(0,15))
|
||||
, batteryLevel(batteryLevel) {}
|
||||
|
||||
void BleKeyboard::begin(void)
|
||||
{
|
||||
BLEDevice::init(deviceName);
|
||||
BLEServer* pServer = BLEDevice::createServer();
|
||||
pServer->setCallbacks(this);
|
||||
|
||||
hid = new BLEHIDDevice(pServer);
|
||||
inputKeyboard = hid->inputReport(KEYBOARD_ID); // <-- input REPORTID from report map
|
||||
outputKeyboard = hid->outputReport(KEYBOARD_ID);
|
||||
inputMediaKeys = hid->inputReport(MEDIA_KEYS_ID);
|
||||
|
||||
outputKeyboard->setCallbacks(this);
|
||||
|
||||
hid->manufacturer()->setValue(deviceManufacturer);
|
||||
|
||||
hid->pnp(0x02, vid, pid, version);
|
||||
hid->hidInfo(0x00, 0x01);
|
||||
|
||||
|
||||
#if defined(USE_NIMBLE)
|
||||
|
||||
BLEDevice::setSecurityAuth(true, true, true);
|
||||
|
||||
#else
|
||||
|
||||
BLESecurity* pSecurity = new BLESecurity();
|
||||
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
|
||||
|
||||
#endif // USE_NIMBLE
|
||||
|
||||
hid->reportMap((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor));
|
||||
hid->startServices();
|
||||
|
||||
onStarted(pServer);
|
||||
|
||||
advertising = pServer->getAdvertising();
|
||||
advertising->setAppearance(HID_KEYBOARD);
|
||||
advertising->addServiceUUID(hid->hidService()->getUUID());
|
||||
advertising->setScanResponse(false);
|
||||
advertising->start();
|
||||
hid->setBatteryLevel(batteryLevel);
|
||||
|
||||
ESP_LOGD(LOG_TAG, "Advertising started!");
|
||||
}
|
||||
|
||||
void BleKeyboard::end(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool BleKeyboard::isConnected(void) {
|
||||
return this->connected;
|
||||
}
|
||||
|
||||
void BleKeyboard::setBatteryLevel(uint8_t level) {
|
||||
this->batteryLevel = level;
|
||||
if (hid != 0)
|
||||
this->hid->setBatteryLevel(this->batteryLevel);
|
||||
}
|
||||
|
||||
//must be called before begin in order to set the name
|
||||
void BleKeyboard::setName(std::string deviceName) {
|
||||
this->deviceName = deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the waiting time (in milliseconds) between multiple keystrokes in NimBLE mode.
|
||||
*
|
||||
* @param ms Time in milliseconds
|
||||
*/
|
||||
void BleKeyboard::setDelay(uint32_t ms) {
|
||||
this->_delay_ms = ms;
|
||||
}
|
||||
|
||||
void BleKeyboard::set_vendor_id(uint16_t vid) {
|
||||
this->vid = vid;
|
||||
}
|
||||
|
||||
void BleKeyboard::set_product_id(uint16_t pid) {
|
||||
this->pid = pid;
|
||||
}
|
||||
|
||||
void BleKeyboard::set_version(uint16_t version) {
|
||||
this->version = version;
|
||||
}
|
||||
|
||||
void BleKeyboard::sendReport(KeyReport* keys)
|
||||
{
|
||||
if (this->isConnected())
|
||||
{
|
||||
this->inputKeyboard->setValue((uint8_t*)keys, sizeof(KeyReport));
|
||||
this->inputKeyboard->notify();
|
||||
#if defined(USE_NIMBLE)
|
||||
// vTaskDelay(delayTicks);
|
||||
this->delay_ms(_delay_ms);
|
||||
#endif // USE_NIMBLE
|
||||
}
|
||||
}
|
||||
|
||||
void BleKeyboard::sendReport(MediaKeyReport* keys)
|
||||
{
|
||||
if (this->isConnected())
|
||||
{
|
||||
this->inputMediaKeys->setValue((uint8_t*)keys, sizeof(MediaKeyReport));
|
||||
this->inputMediaKeys->notify();
|
||||
#if defined(USE_NIMBLE)
|
||||
//vTaskDelay(delayTicks);
|
||||
this->delay_ms(_delay_ms);
|
||||
#endif // USE_NIMBLE
|
||||
}
|
||||
}
|
||||
|
||||
extern
|
||||
const uint8_t _asciimap[128] PROGMEM;
|
||||
|
||||
#define SHIFT 0x80
|
||||
const uint8_t _asciimap[128] =
|
||||
{
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e|SHIFT, // !
|
||||
0x34|SHIFT, // "
|
||||
0x20|SHIFT, // #
|
||||
0x21|SHIFT, // $
|
||||
0x22|SHIFT, // %
|
||||
0x24|SHIFT, // &
|
||||
0x34, // '
|
||||
0x26|SHIFT, // (
|
||||
0x27|SHIFT, // )
|
||||
0x25|SHIFT, // *
|
||||
0x2e|SHIFT, // +
|
||||
0x36, // ,
|
||||
0x2d, // -
|
||||
0x37, // .
|
||||
0x38, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x33|SHIFT, // :
|
||||
0x33, // ;
|
||||
0x36|SHIFT, // <
|
||||
0x2e, // =
|
||||
0x37|SHIFT, // >
|
||||
0x38|SHIFT, // ?
|
||||
0x1f|SHIFT, // @
|
||||
0x04|SHIFT, // A
|
||||
0x05|SHIFT, // B
|
||||
0x06|SHIFT, // C
|
||||
0x07|SHIFT, // D
|
||||
0x08|SHIFT, // E
|
||||
0x09|SHIFT, // F
|
||||
0x0a|SHIFT, // G
|
||||
0x0b|SHIFT, // H
|
||||
0x0c|SHIFT, // I
|
||||
0x0d|SHIFT, // J
|
||||
0x0e|SHIFT, // K
|
||||
0x0f|SHIFT, // L
|
||||
0x10|SHIFT, // M
|
||||
0x11|SHIFT, // N
|
||||
0x12|SHIFT, // O
|
||||
0x13|SHIFT, // P
|
||||
0x14|SHIFT, // Q
|
||||
0x15|SHIFT, // R
|
||||
0x16|SHIFT, // S
|
||||
0x17|SHIFT, // T
|
||||
0x18|SHIFT, // U
|
||||
0x19|SHIFT, // V
|
||||
0x1a|SHIFT, // W
|
||||
0x1b|SHIFT, // X
|
||||
0x1c|SHIFT, // Y
|
||||
0x1d|SHIFT, // Z
|
||||
0x2f, // [
|
||||
0x31, // bslash
|
||||
0x30, // ]
|
||||
0x23|SHIFT, // ^
|
||||
0x2d|SHIFT, // _
|
||||
0x35, // `
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x2f|SHIFT, // {
|
||||
0x31|SHIFT, // |
|
||||
0x30|SHIFT, // }
|
||||
0x35|SHIFT, // ~
|
||||
0 // DEL
|
||||
};
|
||||
|
||||
|
||||
uint8_t USBPutChar(uint8_t c);
|
||||
|
||||
// press() adds the specified key (printing, non-printing, or modifier)
|
||||
// to the persistent key report and sends the report. Because of the way
|
||||
// USB HID works, the host acts like the key remains pressed until we
|
||||
// call release(), releaseAll(), or otherwise clear the report and resend.
|
||||
size_t BleKeyboard::press(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers |= (1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Add k to the key report only if it's not already present
|
||||
// and if there is an empty slot.
|
||||
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
if (_keyReport.keys[i] == 0x00) {
|
||||
_keyReport.keys[i] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t BleKeyboard::press(const MediaKeyReport k)
|
||||
{
|
||||
uint16_t k_16 = k[1] | (k[0] << 8);
|
||||
uint16_t mediaKeyReport_16 = _mediaKeyReport[1] | (_mediaKeyReport[0] << 8);
|
||||
|
||||
mediaKeyReport_16 |= k_16;
|
||||
_mediaKeyReport[0] = (uint8_t)((mediaKeyReport_16 & 0xFF00) >> 8);
|
||||
_mediaKeyReport[1] = (uint8_t)(mediaKeyReport_16 & 0x00FF);
|
||||
|
||||
sendReport(&_mediaKeyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// release() takes the specified key out of the persistent key report and
|
||||
// sends the report. This tells the OS the key is no longer pressed and that
|
||||
// it shouldn't be repeated any more.
|
||||
size_t BleKeyboard::release(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers &= ~(1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the key report to see if k is present. Clear it if it exists.
|
||||
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||
for (i=0; i<6; i++) {
|
||||
if (0 != k && _keyReport.keys[i] == k) {
|
||||
_keyReport.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t BleKeyboard::release(const MediaKeyReport k)
|
||||
{
|
||||
uint16_t k_16 = k[1] | (k[0] << 8);
|
||||
uint16_t mediaKeyReport_16 = _mediaKeyReport[1] | (_mediaKeyReport[0] << 8);
|
||||
mediaKeyReport_16 &= ~k_16;
|
||||
_mediaKeyReport[0] = (uint8_t)((mediaKeyReport_16 & 0xFF00) >> 8);
|
||||
_mediaKeyReport[1] = (uint8_t)(mediaKeyReport_16 & 0x00FF);
|
||||
|
||||
sendReport(&_mediaKeyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BleKeyboard::releaseAll(void)
|
||||
{
|
||||
_keyReport.keys[0] = 0;
|
||||
_keyReport.keys[1] = 0;
|
||||
_keyReport.keys[2] = 0;
|
||||
_keyReport.keys[3] = 0;
|
||||
_keyReport.keys[4] = 0;
|
||||
_keyReport.keys[5] = 0;
|
||||
_keyReport.modifiers = 0;
|
||||
_mediaKeyReport[0] = 0;
|
||||
_mediaKeyReport[1] = 0;
|
||||
sendReport(&_keyReport);
|
||||
}
|
||||
|
||||
size_t BleKeyboard::write(uint8_t c)
|
||||
{
|
||||
uint8_t p = press(c); // Keydown
|
||||
release(c); // Keyup
|
||||
return p; // just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
size_t BleKeyboard::write(const MediaKeyReport c)
|
||||
{
|
||||
uint16_t p = press(c); // Keydown
|
||||
release(c); // Keyup
|
||||
return p; // just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
size_t BleKeyboard::write(const uint8_t *buffer, size_t size) {
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (*buffer != '\r') {
|
||||
if (write(*buffer)) {
|
||||
n++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void BleKeyboard::onConnect(BLEServer* pServer) {
|
||||
this->connected = true;
|
||||
|
||||
#if !defined(USE_NIMBLE)
|
||||
|
||||
BLE2902* desc = (BLE2902*)this->inputKeyboard->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
|
||||
desc->setNotifications(true);
|
||||
desc = (BLE2902*)this->inputMediaKeys->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
|
||||
desc->setNotifications(true);
|
||||
|
||||
#endif // !USE_NIMBLE
|
||||
|
||||
}
|
||||
|
||||
void BleKeyboard::onDisconnect(BLEServer* pServer) {
|
||||
this->connected = false;
|
||||
|
||||
#if !defined(USE_NIMBLE)
|
||||
|
||||
BLE2902* desc = (BLE2902*)this->inputKeyboard->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
|
||||
desc->setNotifications(false);
|
||||
desc = (BLE2902*)this->inputMediaKeys->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
|
||||
desc->setNotifications(false);
|
||||
|
||||
advertising->start();
|
||||
|
||||
#endif // !USE_NIMBLE
|
||||
}
|
||||
|
||||
void BleKeyboard::onWrite(BLECharacteristic* me) {
|
||||
uint8_t* value = (uint8_t*)(me->getValue().c_str());
|
||||
(void)value;
|
||||
ESP_LOGI(LOG_TAG, "special keys: %d", *value);
|
||||
}
|
||||
|
||||
void BleKeyboard::delay_ms(uint64_t ms) {
|
||||
uint64_t m = esp_timer_get_time();
|
||||
if(ms){
|
||||
uint64_t e = (m + (ms * 1000));
|
||||
if(m > e){ //overflow
|
||||
while(esp_timer_get_time() > e) { }
|
||||
}
|
||||
while(esp_timer_get_time() < e) {}
|
||||
}
|
||||
}
|
189
Platformio/lib/ESP32-BLE-Keyboard/BleKeyboard.h
Normal file
189
Platformio/lib/ESP32-BLE-Keyboard/BleKeyboard.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
// uncomment the following line to use NimBLE library
|
||||
//#define USE_NIMBLE
|
||||
|
||||
#ifndef ESP32_BLE_KEYBOARD_H
|
||||
#define ESP32_BLE_KEYBOARD_H
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#if defined(USE_NIMBLE)
|
||||
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLEHIDDevice.h"
|
||||
|
||||
#define BLEDevice NimBLEDevice
|
||||
#define BLEServerCallbacks NimBLEServerCallbacks
|
||||
#define BLECharacteristicCallbacks NimBLECharacteristicCallbacks
|
||||
#define BLEHIDDevice NimBLEHIDDevice
|
||||
#define BLECharacteristic NimBLECharacteristic
|
||||
#define BLEAdvertising NimBLEAdvertising
|
||||
#define BLEServer NimBLEServer
|
||||
|
||||
#else
|
||||
|
||||
#include "BLEHIDDevice.h"
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
#endif // USE_NIMBLE
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
#define BLE_KEYBOARD_VERSION "0.0.4"
|
||||
#define BLE_KEYBOARD_VERSION_MAJOR 0
|
||||
#define BLE_KEYBOARD_VERSION_MINOR 0
|
||||
#define BLE_KEYBOARD_VERSION_REVISION 4
|
||||
|
||||
const uint8_t KEY_LEFT_CTRL = 0x80;
|
||||
const uint8_t KEY_LEFT_SHIFT = 0x81;
|
||||
const uint8_t KEY_LEFT_ALT = 0x82;
|
||||
const uint8_t KEY_LEFT_GUI = 0x83;
|
||||
const uint8_t KEY_RIGHT_CTRL = 0x84;
|
||||
const uint8_t KEY_RIGHT_SHIFT = 0x85;
|
||||
const uint8_t KEY_RIGHT_ALT = 0x86;
|
||||
const uint8_t KEY_RIGHT_GUI = 0x87;
|
||||
|
||||
const uint8_t KEY_UP_ARROW = 0xDA;
|
||||
const uint8_t KEY_DOWN_ARROW = 0xD9;
|
||||
const uint8_t KEY_LEFT_ARROW = 0xD8;
|
||||
const uint8_t KEY_RIGHT_ARROW = 0xD7;
|
||||
const uint8_t KEY_BACKSPACE = 0xB2;
|
||||
const uint8_t KEY_TAB = 0xB3;
|
||||
const uint8_t KEY_RETURN = 0xB0;
|
||||
const uint8_t KEY_ESC = 0xB1;
|
||||
const uint8_t KEY_INSERT = 0xD1;
|
||||
const uint8_t KEY_PRTSC = 0xCE;
|
||||
const uint8_t KEY_DELETE = 0xD4;
|
||||
const uint8_t KEY_PAGE_UP = 0xD3;
|
||||
const uint8_t KEY_PAGE_DOWN = 0xD6;
|
||||
const uint8_t KEY_HOME = 0xD2;
|
||||
const uint8_t KEY_END = 0xD5;
|
||||
const uint8_t KEY_CAPS_LOCK = 0xC1;
|
||||
const uint8_t KEY_F1 = 0xC2;
|
||||
const uint8_t KEY_F2 = 0xC3;
|
||||
const uint8_t KEY_F3 = 0xC4;
|
||||
const uint8_t KEY_F4 = 0xC5;
|
||||
const uint8_t KEY_F5 = 0xC6;
|
||||
const uint8_t KEY_F6 = 0xC7;
|
||||
const uint8_t KEY_F7 = 0xC8;
|
||||
const uint8_t KEY_F8 = 0xC9;
|
||||
const uint8_t KEY_F9 = 0xCA;
|
||||
const uint8_t KEY_F10 = 0xCB;
|
||||
const uint8_t KEY_F11 = 0xCC;
|
||||
const uint8_t KEY_F12 = 0xCD;
|
||||
const uint8_t KEY_F13 = 0xF0;
|
||||
const uint8_t KEY_F14 = 0xF1;
|
||||
const uint8_t KEY_F15 = 0xF2;
|
||||
const uint8_t KEY_F16 = 0xF3;
|
||||
const uint8_t KEY_F17 = 0xF4;
|
||||
const uint8_t KEY_F18 = 0xF5;
|
||||
const uint8_t KEY_F19 = 0xF6;
|
||||
const uint8_t KEY_F20 = 0xF7;
|
||||
const uint8_t KEY_F21 = 0xF8;
|
||||
const uint8_t KEY_F22 = 0xF9;
|
||||
const uint8_t KEY_F23 = 0xFA;
|
||||
const uint8_t KEY_F24 = 0xFB;
|
||||
|
||||
const uint8_t KEY_NUM_0 = 0xEA;
|
||||
const uint8_t KEY_NUM_1 = 0xE1;
|
||||
const uint8_t KEY_NUM_2 = 0xE2;
|
||||
const uint8_t KEY_NUM_3 = 0xE3;
|
||||
const uint8_t KEY_NUM_4 = 0xE4;
|
||||
const uint8_t KEY_NUM_5 = 0xE5;
|
||||
const uint8_t KEY_NUM_6 = 0xE6;
|
||||
const uint8_t KEY_NUM_7 = 0xE7;
|
||||
const uint8_t KEY_NUM_8 = 0xE8;
|
||||
const uint8_t KEY_NUM_9 = 0xE9;
|
||||
const uint8_t KEY_NUM_SLASH = 0xDC;
|
||||
const uint8_t KEY_NUM_ASTERISK = 0xDD;
|
||||
const uint8_t KEY_NUM_MINUS = 0xDE;
|
||||
const uint8_t KEY_NUM_PLUS = 0xDF;
|
||||
const uint8_t KEY_NUM_ENTER = 0xE0;
|
||||
const uint8_t KEY_NUM_PERIOD = 0xEB;
|
||||
|
||||
typedef uint8_t MediaKeyReport[2];
|
||||
|
||||
const MediaKeyReport KEY_MEDIA_NEXT_TRACK = {1, 0};
|
||||
const MediaKeyReport KEY_MEDIA_PREVIOUS_TRACK = {2, 0};
|
||||
const MediaKeyReport KEY_MEDIA_STOP = {4, 0};
|
||||
const MediaKeyReport KEY_MEDIA_PLAY_PAUSE = {8, 0};
|
||||
const MediaKeyReport KEY_MEDIA_MUTE = {16, 0};
|
||||
const MediaKeyReport KEY_MEDIA_VOLUME_UP = {32, 0};
|
||||
const MediaKeyReport KEY_MEDIA_VOLUME_DOWN = {64, 0};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_HOME = {128, 0};
|
||||
const MediaKeyReport KEY_MEDIA_LOCAL_MACHINE_BROWSER = {0, 1}; // Opens "My Computer" on Windows
|
||||
// original from BLE-Keyboard
|
||||
// const MediaKeyReport KEY_MEDIA_CALCULATOR = {0, 2};
|
||||
// changed for usage in OMOTE
|
||||
const MediaKeyReport KEY_MEDIA_FASTFORWARD = {0, 2};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_BOOKMARKS = {0, 4};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_SEARCH = {0, 8};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_STOP = {0, 16};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_BACK = {0, 32};
|
||||
const MediaKeyReport KEY_MEDIA_CONSUMER_CONTROL_CONFIGURATION = {0, 64}; // Media Selection
|
||||
// original from BLE-Keyboard
|
||||
// const MediaKeyReport KEY_MEDIA_EMAIL_READER = {0, 128};
|
||||
// changed for usage in OMOTE
|
||||
const MediaKeyReport KEY_MEDIA_REWIND = {0, 128};
|
||||
|
||||
|
||||
// Low level key report: up to 6 keys and shift, ctrl etc at once
|
||||
typedef struct
|
||||
{
|
||||
uint8_t modifiers;
|
||||
uint8_t reserved;
|
||||
uint8_t keys[6];
|
||||
} KeyReport;
|
||||
|
||||
class BleKeyboard : public Print, public BLEServerCallbacks, public BLECharacteristicCallbacks
|
||||
{
|
||||
private:
|
||||
BLEHIDDevice* hid;
|
||||
BLECharacteristic* inputKeyboard;
|
||||
BLECharacteristic* outputKeyboard;
|
||||
BLECharacteristic* inputMediaKeys;
|
||||
BLEAdvertising* advertising;
|
||||
KeyReport _keyReport;
|
||||
MediaKeyReport _mediaKeyReport;
|
||||
std::string deviceName;
|
||||
std::string deviceManufacturer;
|
||||
uint8_t batteryLevel;
|
||||
bool connected = false;
|
||||
uint32_t _delay_ms = 7;
|
||||
void delay_ms(uint64_t ms);
|
||||
|
||||
uint16_t vid = 0x05ac;
|
||||
uint16_t pid = 0x820a;
|
||||
uint16_t version = 0x0210;
|
||||
|
||||
public:
|
||||
BleKeyboard(std::string deviceName = "ESP32 Keyboard", std::string deviceManufacturer = "Espressif", uint8_t batteryLevel = 100);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void sendReport(KeyReport* keys);
|
||||
void sendReport(MediaKeyReport* keys);
|
||||
size_t press(uint8_t k);
|
||||
size_t press(const MediaKeyReport k);
|
||||
size_t release(uint8_t k);
|
||||
size_t release(const MediaKeyReport k);
|
||||
size_t write(uint8_t c);
|
||||
size_t write(const MediaKeyReport c);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
void releaseAll(void);
|
||||
bool isConnected(void);
|
||||
void setBatteryLevel(uint8_t level);
|
||||
void setName(std::string deviceName);
|
||||
void setDelay(uint32_t ms);
|
||||
|
||||
void set_vendor_id(uint16_t vid);
|
||||
void set_product_id(uint16_t pid);
|
||||
void set_version(uint16_t version);
|
||||
protected:
|
||||
virtual void onStarted(BLEServer *pServer) { };
|
||||
virtual void onConnect(BLEServer* pServer) override;
|
||||
virtual void onDisconnect(BLEServer* pServer) override;
|
||||
virtual void onWrite(BLECharacteristic* me) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif // ESP32_BLE_KEYBOARD_H
|
162
Platformio/lib/ESP32-BLE-Keyboard/README.md
Normal file
162
Platformio/lib/ESP32-BLE-Keyboard/README.md
Normal file
|
@ -0,0 +1,162 @@
|
|||
# ESP32 BLE Keyboard library
|
||||
|
||||
This library allows you to make the ESP32 act as a Bluetooth Keyboard and control what it does.
|
||||
You might also be interested in:
|
||||
- [ESP32-BLE-Mouse](https://github.com/T-vK/ESP32-BLE-Mouse)
|
||||
- [ESP32-BLE-Gamepad](https://github.com/lemmingDev/ESP32-BLE-Gamepad)
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- [x] Send key strokes
|
||||
- [x] Send text
|
||||
- [x] Press/release individual keys
|
||||
- [x] Media keys are supported
|
||||
- [ ] Read Numlock/Capslock/Scrolllock state
|
||||
- [x] Set battery level (basically works, but doesn't show up in Android's status bar)
|
||||
- [x] Compatible with Android
|
||||
- [x] Compatible with Windows
|
||||
- [x] Compatible with Linux
|
||||
- [x] Compatible with MacOS X (not stable, some people have issues, doesn't work with old devices)
|
||||
- [x] Compatible with iOS (not stable, some people have issues, doesn't work with old devices)
|
||||
|
||||
## Installation
|
||||
- (Make sure you can use the ESP32 with the Arduino IDE. [Instructions can be found here.](https://github.com/espressif/arduino-esp32#installation-instructions))
|
||||
- [Download the latest release of this library from the release page.](https://github.com/T-vK/ESP32-BLE-Keyboard/releases)
|
||||
- In the Arduino IDE go to "Sketch" -> "Include Library" -> "Add .ZIP Library..." and select the file you just downloaded.
|
||||
- You can now go to "File" -> "Examples" -> "ESP32 BLE Keyboard" and select any of the examples to get started.
|
||||
|
||||
## Example
|
||||
|
||||
``` C++
|
||||
/**
|
||||
* This example turns the ESP32 into a Bluetooth LE keyboard that writes the words, presses Enter, presses a media key and then Ctrl+Alt+Delete
|
||||
*/
|
||||
#include <BleKeyboard.h>
|
||||
|
||||
BleKeyboard bleKeyboard;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting BLE work!");
|
||||
bleKeyboard.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(bleKeyboard.isConnected()) {
|
||||
Serial.println("Sending 'Hello world'...");
|
||||
bleKeyboard.print("Hello world");
|
||||
|
||||
delay(1000);
|
||||
|
||||
Serial.println("Sending Enter key...");
|
||||
bleKeyboard.write(KEY_RETURN);
|
||||
|
||||
delay(1000);
|
||||
|
||||
Serial.println("Sending Play/Pause media key...");
|
||||
bleKeyboard.write(KEY_MEDIA_PLAY_PAUSE);
|
||||
|
||||
delay(1000);
|
||||
|
||||
//
|
||||
// Below is an example of pressing multiple keyboard modifiers
|
||||
// which by default is commented out.
|
||||
//
|
||||
/* Serial.println("Sending Ctrl+Alt+Delete...");
|
||||
bleKeyboard.press(KEY_LEFT_CTRL);
|
||||
bleKeyboard.press(KEY_LEFT_ALT);
|
||||
bleKeyboard.press(KEY_DELETE);
|
||||
delay(100);
|
||||
bleKeyboard.releaseAll();
|
||||
*/
|
||||
|
||||
}
|
||||
Serial.println("Waiting 5 seconds...");
|
||||
delay(5000);
|
||||
}
|
||||
```
|
||||
|
||||
## API docs
|
||||
The BleKeyboard interface is almost identical to the Keyboard Interface, so you can use documentation right here:
|
||||
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
|
||||
|
||||
Just remember that you have to use `bleKeyboard` instead of just `Keyboard` and you need these two lines at the top of your script:
|
||||
```
|
||||
#include <BleKeyboard.h>
|
||||
BleKeyboard bleKeyboard;
|
||||
```
|
||||
|
||||
In addition to that you can send media keys (which is not possible with the USB keyboard library). Supported are the following:
|
||||
- KEY_MEDIA_NEXT_TRACK
|
||||
- KEY_MEDIA_PREVIOUS_TRACK
|
||||
- KEY_MEDIA_STOP
|
||||
- KEY_MEDIA_PLAY_PAUSE
|
||||
- KEY_MEDIA_MUTE
|
||||
- KEY_MEDIA_VOLUME_UP
|
||||
- KEY_MEDIA_VOLUME_DOWN
|
||||
- KEY_MEDIA_WWW_HOME
|
||||
- KEY_MEDIA_LOCAL_MACHINE_BROWSER // Opens "My Computer" on Windows
|
||||
- KEY_MEDIA_CALCULATOR
|
||||
- KEY_MEDIA_WWW_BOOKMARKS
|
||||
- KEY_MEDIA_WWW_SEARCH
|
||||
- KEY_MEDIA_WWW_STOP
|
||||
- KEY_MEDIA_WWW_BACK
|
||||
- KEY_MEDIA_CONSUMER_CONTROL_CONFIGURATION // Media Selection
|
||||
- KEY_MEDIA_EMAIL_READER
|
||||
|
||||
There is also Bluetooth specific information that you can set (optional):
|
||||
Instead of `BleKeyboard bleKeyboard;` you can do `BleKeyboard bleKeyboard("Bluetooth Device Name", "Bluetooth Device Manufacturer", 100);`. (Max lenght is 15 characters, anything beyond that will be truncated.)
|
||||
The third parameter is the initial battery level of your device. To adjust the battery level later on you can simply call e.g. `bleKeyboard.setBatteryLevel(50)` (set battery level to 50%).
|
||||
By default the battery level will be set to 100%, the device name will be `ESP32 Bluetooth Keyboard` and the manufacturer will be `Espressif`.
|
||||
There is also a `setDelay` method to set a delay between each key event. E.g. `bleKeyboard.setDelay(10)` (10 milliseconds). The default is `8`.
|
||||
This feature is meant to compensate for some applications and devices that can't handle fast input and will skip letters if too many keys are sent in a small time frame.
|
||||
|
||||
## NimBLE-Mode
|
||||
The NimBLE mode enables a significant saving of RAM and FLASH memory.
|
||||
|
||||
### Comparison (SendKeyStrokes.ino at compile-time)
|
||||
|
||||
**Standard**
|
||||
```
|
||||
RAM: [= ] 9.3% (used 30548 bytes from 327680 bytes)
|
||||
Flash: [======== ] 75.8% (used 994120 bytes from 1310720 bytes)
|
||||
```
|
||||
|
||||
**NimBLE mode**
|
||||
```
|
||||
RAM: [= ] 8.3% (used 27180 bytes from 327680 bytes)
|
||||
Flash: [==== ] 44.2% (used 579158 bytes from 1310720 bytes)
|
||||
```
|
||||
|
||||
### Comparison (SendKeyStrokes.ino at run-time)
|
||||
|
||||
| | Standard | NimBLE mode | difference
|
||||
|---|--:|--:|--:|
|
||||
| `ESP.getHeapSize()` | 296.804 | 321.252 | **+ 24.448** |
|
||||
| `ESP.getFreeHeap()` | 143.572 | 260.764 | **+ 117.192** |
|
||||
| `ESP.getSketchSize()` | 994.224 | 579.264 | **- 414.960** |
|
||||
|
||||
## How to activate NimBLE mode?
|
||||
|
||||
### ArduinoIDE:
|
||||
Uncomment the first line in BleKeyboard.h
|
||||
```C++
|
||||
#define USE_NIMBLE
|
||||
```
|
||||
|
||||
### PlatformIO:
|
||||
Change your `platformio.ini` to the following settings
|
||||
```ini
|
||||
lib_deps =
|
||||
NimBLE-Arduino
|
||||
|
||||
build_flags =
|
||||
-D USE_NIMBLE
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
Credits to [chegewara](https://github.com/chegewara) and [the authors of the USB keyboard library](https://github.com/arduino-libraries/Keyboard/) as this project is heavily based on their work!
|
||||
Also, credits to [duke2421](https://github.com/T-vK/ESP32-BLE-Keyboard/issues/1) who helped a lot with testing, debugging and fixing the device descriptor!
|
||||
And credits to [sivar2311](https://github.com/sivar2311) for adding NimBLE support, greatly reducing the memory footprint, fixing advertising issues and for adding the `setDelay` method.
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* This example turns the ESP32 into a Bluetooth LE keyboard that writes the words, presses Enter, presses a media key and then Ctrl+Alt+Delete
|
||||
*/
|
||||
#include <BleKeyboard.h>
|
||||
|
||||
BleKeyboard bleKeyboard;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting BLE work!");
|
||||
bleKeyboard.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(bleKeyboard.isConnected()) {
|
||||
Serial.println("Sending 'Hello world'...");
|
||||
bleKeyboard.print("Hello world");
|
||||
|
||||
delay(1000);
|
||||
|
||||
Serial.println("Sending Enter key...");
|
||||
bleKeyboard.write(KEY_RETURN);
|
||||
|
||||
delay(1000);
|
||||
|
||||
Serial.println("Sending Play/Pause media key...");
|
||||
bleKeyboard.write(KEY_MEDIA_PLAY_PAUSE);
|
||||
|
||||
delay(1000);
|
||||
|
||||
//
|
||||
// Below is an example of pressing multiple keyboard modifiers
|
||||
// which by default is commented out.
|
||||
/*
|
||||
Serial.println("Sending Ctrl+Alt+Delete...");
|
||||
bleKeyboard.press(KEY_LEFT_CTRL);
|
||||
bleKeyboard.press(KEY_LEFT_ALT);
|
||||
bleKeyboard.press(KEY_DELETE);
|
||||
delay(100);
|
||||
bleKeyboard.releaseAll();
|
||||
*/
|
||||
}
|
||||
|
||||
Serial.println("Waiting 5 seconds...");
|
||||
delay(5000);
|
||||
}
|
24
Platformio/lib/ESP32-BLE-Keyboard/keywords.txt
Normal file
24
Platformio/lib/ESP32-BLE-Keyboard/keywords.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map For ESP32 BLE Keyboard
|
||||
#######################################
|
||||
# Class
|
||||
#######################################
|
||||
|
||||
BleKeyboard KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
write KEYWORD2
|
||||
press KEYWORD2
|
||||
release KEYWORD2
|
||||
releaseAll KEYWORD2
|
||||
setBatteryLevel KEYWORD2
|
||||
isConnected KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants
|
||||
#######################################
|
9
Platformio/lib/ESP32-BLE-Keyboard/library.properties
Normal file
9
Platformio/lib/ESP32-BLE-Keyboard/library.properties
Normal file
|
@ -0,0 +1,9 @@
|
|||
name=ESP32 BLE Keyboard
|
||||
version=0.3.2
|
||||
author=T-vK
|
||||
maintainer=T-vK
|
||||
sentence=Bluetooth LE Keyboard library for the ESP32.
|
||||
paragraph=Bluetooth LE Keyboard library for the ESP32.
|
||||
category=Communication
|
||||
url=https://github.com/T-vK/ESP32-BLE-Keyboard
|
||||
architectures=esp32
|
|
@ -15,7 +15,7 @@ byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad
|
|||
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
|
||||
|
||||
unsigned long loopCount = 0;
|
||||
unsigned long timer_t = 0;
|
||||
unsigned long timer_ms = 0;
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
@ -33,12 +33,12 @@ void loop(){
|
|||
// you a relative idea of just how much the debounceTime has changed the
|
||||
// speed of your code. If you set a high debounceTime your loopCount will
|
||||
// look good but your keypresses will start to feel sluggish.
|
||||
if ((millis() - timer_t) > 1000) {
|
||||
if ((millis() - timer_ms) > 1000) {
|
||||
Serial.print("Your loop code ran ");
|
||||
Serial.print(loopCount);
|
||||
Serial.println(" times over the last second");
|
||||
loopCount = 0;
|
||||
timer_t = millis();
|
||||
timer_ms = millis();
|
||||
}
|
||||
loopCount++;
|
||||
if(key)
|
||||
|
|
|
@ -83,18 +83,31 @@ bool Keypad::getKeys() {
|
|||
void Keypad::scanKeys() {
|
||||
// Re-intialize the row pins. Allows sharing these pins with other hardware.
|
||||
for (byte r=0; r<sizeKpd.rows; r++) {
|
||||
// Logic needs to be inverted. This way the ESP32’s EXT1 wakeup can be used to detect if the accelerometer pin or any button pin goes high
|
||||
// original from Keypad
|
||||
// pin_mode(rowPins[r],INPUT_PULLUP);
|
||||
// changed for usage in OMOTE
|
||||
pin_mode(rowPins[r],INPUT);
|
||||
}
|
||||
|
||||
// bitMap stores ALL the keys that are being pressed.
|
||||
for (byte c=0; c<sizeKpd.columns; c++) {
|
||||
pin_mode(columnPins[c],OUTPUT);
|
||||
// original from Keypad
|
||||
// pin_write(columnPins[c], LOW); // Begin column pulse output.
|
||||
// changed for usage in OMOTE
|
||||
pin_write(columnPins[c], HIGH); // Begin column pulse output.
|
||||
for (byte r=0; r<sizeKpd.rows; r++) {
|
||||
// original from Keypad
|
||||
// bitWrite(bitMap[r], c, !pin_read(rowPins[r])); // keypress is active low so invert to high.
|
||||
// changed for usage in OMOTE
|
||||
bitWrite(bitMap[r], c, pin_read(rowPins[r])); // keypress is active low so invert to high.
|
||||
}
|
||||
// Set pin to high impedance input. Effectively ends column pulse.
|
||||
pin_write(columnPins[c],LOW);
|
||||
// original from Keypad
|
||||
// pin_write(columnPins[c],HIGH);
|
||||
// changed for usage in OMOTE
|
||||
pin_write(columnPins[c], LOW);
|
||||
pin_mode(columnPins[c],INPUT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,22 @@
|
|||
|
||||
#include "Key.h"
|
||||
|
||||
// bperrybap - Thanks for a well reasoned argument and the following macro(s).
|
||||
// See http://arduino.cc/forum/index.php/topic,142041.msg1069480.html#msg1069480
|
||||
#ifndef INPUT_PULLUP
|
||||
#warning "Using pinMode() INPUT_PULLUP AVR emulation"
|
||||
#define INPUT_PULLUP 0x2
|
||||
#define pinMode(_pin, _mode) _mypinMode(_pin, _mode)
|
||||
#define _mypinMode(_pin, _mode) \
|
||||
do { \
|
||||
if(_mode == INPUT_PULLUP) \
|
||||
pinMode(_pin, INPUT); \
|
||||
digitalWrite(_pin, 1); \
|
||||
if(_mode != INPUT_PULLUP) \
|
||||
pinMode(_pin, _mode); \
|
||||
}while(0)
|
||||
#endif
|
||||
|
||||
|
||||
#define OPEN LOW
|
||||
#define CLOSED HIGH
|
||||
|
|
|
@ -24,9 +24,13 @@ lib_deps =
|
|||
lvgl/lvgl@^8.3.4
|
||||
bodmer/TFT_eSPI@^2.5.23
|
||||
knolleary/PubSubClient@^2.8
|
||||
h2zero/NimBLE-Arduino@^1.4.1
|
||||
;t-vk/ESP32 BLE Keyboard@^0.3.2
|
||||
build_flags =
|
||||
-D DISABLE_ALL_LIBRARY_WARNINGS=1 ; for TFT_eSPI
|
||||
-D USE_NIMBLE=1 ; for BLE Keyboard
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-I include ; Include the folder containing lv_conf.h
|
||||
-D LV_CONF_PATH=../../../../src/gui_general_and_keys/lv_conf.h
|
||||
; The following lines replace the TFT_eSPI User_setup.h-file
|
||||
-D USER_SETUP_LOADED=1
|
||||
-D ILI9341_DRIVER=1
|
||||
|
|
190
Platformio/src/commandHandler.cpp
Normal file
190
Platformio/src/commandHandler.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
#include "hardware/infrared_sender.h"
|
||||
#include "hardware/mqtt.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "device_keyboard_mqtt/device_keyboard_mqtt.h"
|
||||
#include "device_keyboard_ble/device_keyboard_ble.h"
|
||||
#include "commandHandler.h"
|
||||
#include "scenes/sceneHandler.h"
|
||||
|
||||
std::map<std::string, commandData> commands;
|
||||
|
||||
commandData makeCommandData(commandHandlers a, std::list<std::string> b) {
|
||||
commandData c = {a, b};
|
||||
return c;
|
||||
}
|
||||
|
||||
void register_specialCommands() {
|
||||
// put SPECIAL commands here if you want
|
||||
commands[MY_SPECIAL_COMMAND] = makeCommandData(SPECIAL, {""});
|
||||
|
||||
}
|
||||
|
||||
void executeCommandWithData(std::string command, commandData commandData, std::string additionalPayload = "") {
|
||||
switch (commandData.commandHandler) {
|
||||
case IR_GC: {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
std::string arrayStr = *current;
|
||||
// first create array of needed size
|
||||
std::string::difference_type size = std::count(arrayStr.begin(), arrayStr.end(), ',');
|
||||
size += 1;
|
||||
uint16_t *buf = new uint16_t[size];
|
||||
// now get comma separated values and fill array
|
||||
int pos = 0;
|
||||
std::stringstream ss(arrayStr);
|
||||
while(ss.good()) {
|
||||
std::string dataStr;
|
||||
std::getline(ss, dataStr, ',');
|
||||
// https://cplusplus.com/reference/string/stoull/
|
||||
std::string::size_type sz = 0; // alias of size_t
|
||||
const uint64_t data = std::stoull(dataStr, &sz, 0);
|
||||
// Serial.printf(" next string value %s (%" PRIu64 ")\r\n", dataStr.c_str(), data);
|
||||
buf[pos] = data;
|
||||
pos += 1;
|
||||
}
|
||||
Serial.printf("execute: will send IR GC, array size %d\r\n", size);
|
||||
IrSender.sendGC(buf, size);
|
||||
delete [] buf;
|
||||
break;
|
||||
}
|
||||
|
||||
case IR_NEC: {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
std::string dataStr = *current;
|
||||
// https://cplusplus.com/reference/string/stoull/
|
||||
std::string::size_type sz = 0; // alias of size_t
|
||||
const uint64_t data = std::stoull(dataStr, &sz, 0);
|
||||
Serial.printf("execute: will send IR NEC, data %s (%" PRIu64 ")\r\n", dataStr.c_str(), data);
|
||||
IrSender.sendNEC(data);
|
||||
break;
|
||||
}
|
||||
|
||||
case IR_SAMSUNG: {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
std::string dataStr = *current;
|
||||
// https://cplusplus.com/reference/string/stoull/
|
||||
std::string::size_type sz = 0; // alias of size_t
|
||||
const uint64_t data = std::stoull(dataStr, &sz, 0);
|
||||
Serial.printf("execute: will send IR SAMSUNG, data %s (%" PRIu64 ")\r\n", dataStr.c_str(), data);
|
||||
IrSender.sendSAMSUNG(data);
|
||||
break;
|
||||
}
|
||||
|
||||
case IR_SONY: {
|
||||
std::string::size_type sz = 0; // alias of size_t
|
||||
uint64_t data;
|
||||
if (commandData.commandPayloads.empty() && (additionalPayload == "")) {
|
||||
Serial.printf("execute: cannot send IR SONY, because both data and payload are empty\r\n");
|
||||
} else {
|
||||
if (additionalPayload != "") {
|
||||
data = std::stoull(additionalPayload, &sz, 0);
|
||||
} else {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
data = std::stoull(*current, &sz, 0);
|
||||
}
|
||||
Serial.printf("execute: will send IR SONY 15 bit, data (%" PRIu64 ")\r\n", data);
|
||||
IrSender.sendSony(data, 15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IR_RC5: {
|
||||
std::string::size_type sz = 0; // alias of size_t
|
||||
uint64_t data;
|
||||
if (commandData.commandPayloads.empty() && (additionalPayload == "")) {
|
||||
Serial.printf("execute: cannot send IR RC5, because both data and payload are empty\r\n");
|
||||
} else {
|
||||
if (additionalPayload != "") {
|
||||
data = std::stoull(additionalPayload, &sz, 0);
|
||||
} else {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
data = std::stoull(*current, &sz, 0);
|
||||
}
|
||||
Serial.printf("execute: will send IR RC5, data (%" PRIu64 ")\r\n", data);
|
||||
IrSender.sendRC5(IrSender.encodeRC5X(0x00, data));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IR_DENON: {
|
||||
std::string::size_type sz = 0; // alias of size_t
|
||||
uint64_t data;
|
||||
if (commandData.commandPayloads.empty() && (additionalPayload == "")) {
|
||||
Serial.printf("execute: cannot send IR DENON 48 bit, because both data and payload are empty\r\n");
|
||||
} else {
|
||||
if (additionalPayload != "") {
|
||||
data = std::stoull(additionalPayload, &sz, 0);
|
||||
} else {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
data = std::stoull(*current, &sz, 0);
|
||||
}
|
||||
Serial.printf("execute: will send IR DENON 48 bit, data (%" PRIu64 ")\r\n", data);
|
||||
IrSender.sendDenon(data, 48);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
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;
|
||||
}
|
||||
Serial.printf("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
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_BLE
|
||||
case BLE_KEYBOARD: {
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
std::string command = *current;
|
||||
std::string payload = "";
|
||||
if (additionalPayload != "") {
|
||||
payload = additionalPayload;
|
||||
}
|
||||
Serial.printf("execute: will send BLE keyboard command, command '%s', payload '%s'\r\n", command.c_str(), payload.c_str());
|
||||
keyboard_ble_executeCommand(command, payload);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SCENE: {
|
||||
// let the sceneHandler do the scene stuff
|
||||
Serial.printf("execute: will send scene command to the sceneHandler\r\n");
|
||||
handleScene(command, commandData, additionalPayload);
|
||||
break;
|
||||
}
|
||||
|
||||
case SPECIAL: {
|
||||
if (command == MY_SPECIAL_COMMAND) {
|
||||
// do your special command here
|
||||
Serial.printf("execute: could execute a special command here, if you define one\r\n");
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void executeCommand(std::string command, std::string additionalPayload) {
|
||||
try {
|
||||
if (commands.count(command) > 0) {
|
||||
Serial.printf("command: will execute command '%s'\r\n", command.c_str());
|
||||
executeCommandWithData(command, commands.at(command), additionalPayload);
|
||||
} else {
|
||||
Serial.printf("command: command '%s' not found\r\n", command.c_str());
|
||||
}
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Serial.printf("executeCommand: internal error, command not registered\r\n");
|
||||
}
|
||||
}
|
127
Platformio/src/commandHandler.h
Normal file
127
Platformio/src/commandHandler.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
#ifndef __COMMANDHANDLER_H__
|
||||
#define __COMMANDHANDLER_H__
|
||||
|
||||
#define ENABLE_WIFI_AND_MQTT // Comment out to disable WiFi
|
||||
#define ENABLE_BLUETOOTH // Comment out to disable Bluetooth
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "device_keyboard_mqtt/device_keyboard_mqtt.h"
|
||||
#include "device_keyboard_ble/device_keyboard_ble.h"
|
||||
|
||||
/*
|
||||
Depending on which keyboard is enabled (BLE or MQTT), we define KEYBOARD_UP, KEYBOARD_DOWN and so on.
|
||||
These defines are used in keys.cpp, gui*.cpp and commandHandler.cpp
|
||||
Example:
|
||||
If BLE is enabled, then KEYBOARD_UP will be the same as KEYBOARD_BLE_UP
|
||||
If MQTT is enabled, then KEYBOARD_UP will be the same as KEYBOARD_MQTT_UP
|
||||
If none of them is enabled, then KEYBOARD_UP will be the same as KEYBOARD_UP
|
||||
Doing so you can switch between the keyboards without changing the UI code (keys.cpp, gui*.cpp and commandHandler.cpp)
|
||||
If you need something different than this behaviour, then you can change the defines below for KEYBOARD_UP, KEYBOARD_DOWN and so on,
|
||||
or you can of course change keys.cpp, gui*.cpp and commandHandler.cpp so that they directly use KEYBOARD_BLE_UP or KEYBOARD_MQTT_UP etc.
|
||||
*/
|
||||
|
||||
#define KEYBOARD_DUMMY_UP "Keyboard_dummy_up"
|
||||
#define KEYBOARD_DUMMY_DOWN "Keyboard_dummy_down"
|
||||
#define KEYBOARD_DUMMY_RIGHT "Keyboard_dummy_right"
|
||||
#define KEYBOARD_DUMMY_LEFT "Keyboard_dummy_left"
|
||||
#define KEYBOARD_DUMMY_SELECT "Keyboard_dummy_select"
|
||||
#define KEYBOARD_DUMMY_SENDSTRING "Keyboard_dummy_sendstring"
|
||||
#define KEYBOARD_DUMMY_BACK "Keyboard_dummy_back"
|
||||
#define KEYBOARD_DUMMY_HOME "Keyboard_dummy_home"
|
||||
#define KEYBOARD_DUMMY_MENU "Keyboard_dummy_menu"
|
||||
#define KEYBOARD_DUMMY_SCAN_PREVIOUS_TRACK "Keyboard_dummy_scan_previous_track"
|
||||
#define KEYBOARD_DUMMY_REWIND_LONG "Keyboard_dummy_rewind_long"
|
||||
#define KEYBOARD_DUMMY_REWIND "Keyboard_dummy_rewind"
|
||||
#define KEYBOARD_DUMMY_PLAYPAUSE "Keyboard_dummy_playpause"
|
||||
#define KEYBOARD_DUMMY_FASTFORWARD "Keyboard_dummy_fastforward"
|
||||
#define KEYBOARD_DUMMY_FASTFORWARD_LONG "Keyboard_dummy_fastforward_long"
|
||||
#define KEYBOARD_DUMMY_SCAN_NEXT_TRACK "Keyboard_dummy_scan_next_track"
|
||||
#define KEYBOARD_DUMMY_MUTE "Keyboard_dummy_mute"
|
||||
#define KEYBOARD_DUMMY_VOLUME_INCREMENT "Keyboard_dummy_volume_increment"
|
||||
#define KEYBOARD_DUMMY_VOLUME_DECREMENT "Keyboard_dummy_volume_decrement"
|
||||
|
||||
#if defined(ENABLE_KEYBOARD_BLE)
|
||||
#define KEYBOARD_PREFIX KEYBOARD_BLE_
|
||||
#elif defined(ENABLE_KEYBOARD_MQTT)
|
||||
#define KEYBOARD_PREFIX KEYBOARD_MQTT_
|
||||
#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.
|
||||
#define KEYBOARD_PREFIX KEYBOARD_DUMMY_
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Concatenate preprocessor tokens A and B without expanding macro definitions
|
||||
* (however, if invoked from a macro, macro arguments are expanded).
|
||||
*/
|
||||
#define PPCAT_NX(A, B) A ## B
|
||||
/*
|
||||
* Concatenate preprocessor tokens A and B after macro-expanding them.
|
||||
*/
|
||||
#define PPCAT(A, B) PPCAT_NX(A, B)
|
||||
|
||||
#define KEYBOARD_UP PPCAT(KEYBOARD_PREFIX, UP)
|
||||
#define KEYBOARD_DOWN PPCAT(KEYBOARD_PREFIX, DOWN)
|
||||
#define KEYBOARD_RIGHT PPCAT(KEYBOARD_PREFIX, RIGHT)
|
||||
#define KEYBOARD_LEFT PPCAT(KEYBOARD_PREFIX, LEFT)
|
||||
#define KEYBOARD_SELECT PPCAT(KEYBOARD_PREFIX, SELECT)
|
||||
#define KEYBOARD_SENDSTRING PPCAT(KEYBOARD_PREFIX, SENDSTRING)
|
||||
#define KEYBOARD_BACK PPCAT(KEYBOARD_PREFIX, BACK)
|
||||
#define KEYBOARD_HOME PPCAT(KEYBOARD_PREFIX, HOME)
|
||||
#define KEYBOARD_MENU PPCAT(KEYBOARD_PREFIX, MENU)
|
||||
#define KEYBOARD_SCAN_PREVIOUS_TRACK PPCAT(KEYBOARD_PREFIX, SCAN_PREVIOUS_TRACK)
|
||||
#define KEYBOARD_REWIND_LONG PPCAT(KEYBOARD_PREFIX, REWIND_LONG)
|
||||
#define KEYBOARD_REWIND PPCAT(KEYBOARD_PREFIX, REWIND)
|
||||
#define KEYBOARD_PLAYPAUSE PPCAT(KEYBOARD_PREFIX, PLAYPAUSE)
|
||||
#define KEYBOARD_FASTFORWARD PPCAT(KEYBOARD_PREFIX, FASTFORWARD)
|
||||
#define KEYBOARD_FASTFORWARD_LONG PPCAT(KEYBOARD_PREFIX, FASTFORWARD_LONG)
|
||||
#define KEYBOARD_SCAN_NEXT_TRACK PPCAT(KEYBOARD_PREFIX, SCAN_NEXT_TRACK)
|
||||
#define KEYBOARD_MUTE PPCAT(KEYBOARD_PREFIX, MUTE)
|
||||
#define KEYBOARD_VOLUME_INCREMENT PPCAT(KEYBOARD_PREFIX, VOLUME_INCREMENT)
|
||||
#define KEYBOARD_VOLUME_DECREMENT PPCAT(KEYBOARD_PREFIX, VOLUME_DECREMENT)
|
||||
|
||||
// Test
|
||||
// https://stackoverflow.com/questions/5256313/c-c-macro-string-concatenation
|
||||
// #define STR(x) #x
|
||||
// #define XSTR(x) STR(x)
|
||||
// #pragma message "1 The value is: " XSTR(KEYBOARD_BLE_UP)
|
||||
// #pragma message "2 The value is: " XSTR(KEYBOARD_MQTT_UP)
|
||||
// #pragma message "3 The value is: " XSTR(KEYBOARD_UP)
|
||||
|
||||
#define MY_SPECIAL_COMMAND "My_special_command"
|
||||
|
||||
enum commandHandlers {
|
||||
SPECIAL,
|
||||
SCENE,
|
||||
IR_GC,
|
||||
IR_NEC,
|
||||
IR_SAMSUNG,
|
||||
IR_SONY,
|
||||
IR_RC5,
|
||||
IR_DENON,
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
MQTT,
|
||||
#endif
|
||||
#ifdef ENABLE_KEYBOARD_BLE
|
||||
BLE_KEYBOARD,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct commandData {
|
||||
commandHandlers commandHandler;
|
||||
std::list<std::string> commandPayloads;
|
||||
};
|
||||
|
||||
commandData makeCommandData(commandHandlers a, std::list<std::string> b);
|
||||
|
||||
extern std::map<std::string, commandData> commands;
|
||||
|
||||
void register_specialCommands();
|
||||
void executeCommand(std::string command, std::string additionalPayload = "");
|
||||
|
||||
#endif /*__COMMANDHANDLER_H__*/
|
6
Platformio/src/device_appleTV/device_appleTV.cpp
Normal file
6
Platformio/src/device_appleTV/device_appleTV.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "commandHandler.h"
|
||||
#include "device_appleTV/device_appleTV.h"
|
||||
|
||||
void register_device_appleTV() {
|
||||
commands[APPLETV_GUI_EVENT_USER_DATA] = makeCommandData(IR_SONY, {}); // payload must be set when calling commandHandler
|
||||
}
|
8
Platformio/src/device_appleTV/device_appleTV.h
Normal file
8
Platformio/src/device_appleTV/device_appleTV.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __DEVICE_APPLETV_H__
|
||||
#define __DEVICE_APPLETV_H__
|
||||
|
||||
#define APPLETV_GUI_EVENT_USER_DATA "AppleTV_gui_event_user_data"
|
||||
|
||||
void register_device_appleTV();
|
||||
|
||||
#endif /*__DEVICE_APPLETV_H__*/
|
73
Platformio/src/device_appleTV/gui_appleTV.cpp
Normal file
73
Platformio/src/device_appleTV/gui_appleTV.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include <lvgl.h>
|
||||
#include "device_appleTV/device_appleTV.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/guiRegistry.h"
|
||||
#include "hardware/tft.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
// LVGL declarations
|
||||
LV_IMG_DECLARE(appleTvIcon);
|
||||
LV_IMG_DECLARE(appleDisplayIcon);
|
||||
LV_IMG_DECLARE(appleBackIcon);
|
||||
|
||||
// Apple Key Event handler
|
||||
static void appleKey_event_cb(lv_event_t* e) {
|
||||
// Send IR command based on the event user data
|
||||
executeCommand(APPLETV_GUI_EVENT_USER_DATA, std::to_string(50 + (int)e->user_data));
|
||||
Serial.println(50 + (int)e->user_data);
|
||||
}
|
||||
|
||||
void init_gui_tab_appleTV(lv_obj_t* tabview) {
|
||||
|
||||
lv_obj_t* tab = lv_tabview_add_tab(tabview, "Apple TV");
|
||||
|
||||
// Add content to the Apple TV tab (3)
|
||||
// Add a nice apple tv logo
|
||||
lv_obj_t* appleImg = lv_img_create(tab);
|
||||
lv_img_set_src(appleImg, &appleTvIcon);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, -60);
|
||||
// create two buttons and add their icons accordingly
|
||||
lv_obj_t* button = lv_btn_create(tab);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)1);
|
||||
|
||||
appleImg = lv_img_create(button);
|
||||
lv_img_set_src(appleImg, &appleBackIcon);
|
||||
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
|
||||
|
||||
button = lv_btn_create(tab);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_RIGHT, -10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)2);
|
||||
|
||||
appleImg = lv_img_create(button);
|
||||
lv_img_set_src(appleImg, &appleDisplayIcon);
|
||||
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
void init_gui_pageIndicator_appleTV(lv_obj_t* panel) {
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Apple TV");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
}
|
||||
|
||||
void register_gui_appleTV(void){
|
||||
register_gui(& init_gui_tab_appleTV, & init_gui_pageIndicator_appleTV);
|
||||
}
|
8
Platformio/src/device_appleTV/gui_appleTV.h
Normal file
8
Platformio/src/device_appleTV/gui_appleTV.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __GUI_APPLETV_H__
|
||||
#define __GUI_APPLETV_H__
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
void register_gui_appleTV(void);
|
||||
|
||||
#endif /*__GUI_APPLETV_H__*/
|
|
@ -5,44 +5,6 @@
|
|||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_GRADIENTLEFT
|
||||
#define LV_ATTRIBUTE_IMG_GRADIENTLEFT
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_GRADIENTLEFT uint8_t gradientLeft_map[] = {
|
||||
0xfa, 0xf2, 0xea, 0xe2, 0xda, 0xd1, 0xc7, 0xbe, 0xb7, 0xae, 0xa6, 0x9e, 0x95, 0x8d, 0x84, 0x7d, 0x74, 0x6c, 0x62, 0x5a, 0x51, 0x48, 0x41, 0x38, 0x2f, 0x28, 0x1f, 0x17, 0x0f, 0x07,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t gradientLeft = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 30,
|
||||
.header.h = 1,
|
||||
.data_size = 30,
|
||||
.data = gradientLeft_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_GRADIENTRIGHT
|
||||
#define LV_ATTRIBUTE_IMG_GRADIENTRIGHT
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_GRADIENTRIGHT uint8_t gradientRight_map[] = {
|
||||
0x07, 0x0f, 0x17, 0x1f, 0x28, 0x2f, 0x38, 0x41, 0x48, 0x51, 0x5a, 0x62, 0x6c, 0x74, 0x7d, 0x84, 0x8d, 0x95, 0x9e, 0xa6, 0xae, 0xb7, 0xbe, 0xc7, 0xd1, 0xda, 0xe2, 0xea, 0xf2, 0xfa,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t gradientRight = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 30,
|
||||
.header.h = 1,
|
||||
.data_size = 30,
|
||||
.data = gradientRight_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_APPLETVICON
|
||||
#define LV_ATTRIBUTE_IMG_APPLETVICON
|
||||
#endif
|
||||
|
@ -183,111 +145,3 @@ const lv_img_dsc_t appleBackIcon = {
|
|||
.data_size = 325,
|
||||
.data = appleBackIcon_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_HIGH_BRIGHTNESS
|
||||
#define LV_ATTRIBUTE_IMG_HIGH_BRIGHTNESS
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_HIGH_BRIGHTNESS uint8_t high_brightness_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbd, 0xcc, 0xbd,
|
||||
0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x0d, 0xbd, 0xcc, 0xbd,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x40, 0xd3, 0xff, 0xfe, 0xd2, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t high_brightness = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 18,
|
||||
.header.h = 18,
|
||||
.data_size = 324,
|
||||
.data = high_brightness_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_LOW_BRIGHTNESS
|
||||
#define LV_ATTRIBUTE_IMG_LOW_BRIGHTNESS
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LOW_BRIGHTNESS uint8_t low_brightness_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0x72, 0x28, 0x00, 0x00,
|
||||
0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x0b, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbc, 0x44,
|
||||
0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x11, 0x0d, 0xbc, 0x44,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x0b, 0x00, 0x40, 0xd3, 0xfe, 0xff, 0xd2, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0x72, 0x28, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t low_brightness = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 16,
|
||||
.header.h = 16,
|
||||
.data_size = 256,
|
||||
.data = low_brightness_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_LIGHTBULB
|
||||
#define LV_ATTRIBUTE_IMG_LIGHTBULB
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LIGHTBULB uint8_t lightbulb_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x16, 0x95, 0xee, 0xff, 0xff, 0xee, 0x94, 0x15, 0x00, 0x00,
|
||||
0x00, 0x27, 0xe3, 0xff, 0xcc, 0x8d, 0x8d, 0xcd, 0xff, 0xe1, 0x26, 0x00,
|
||||
0x07, 0xd9, 0xfa, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xfa, 0xd7, 0x06,
|
||||
0x65, 0xff, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xff, 0x63,
|
||||
0xb1, 0xf8, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf8, 0xaf,
|
||||
0xcc, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xcd,
|
||||
0xb1, 0xf5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf1, 0xbd,
|
||||
0x73, 0xff, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xff, 0x74,
|
||||
0x0b, 0xd5, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfb, 0xd9, 0x0b,
|
||||
0x00, 0x24, 0xef, 0xdc, 0x01, 0x00, 0x00, 0x01, 0xdd, 0xee, 0x24, 0x00,
|
||||
0x00, 0x00, 0x83, 0xff, 0x30, 0x00, 0x00, 0x30, 0xff, 0x81, 0x00, 0x00,
|
||||
0x00, 0x00, 0x12, 0x6c, 0x06, 0x00, 0x00, 0x06, 0x6c, 0x12, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0x25, 0x00, 0x00,
|
||||
0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0x25, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1c, 0x76, 0x77, 0x77, 0x76, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x69, 0xff, 0xff, 0xff, 0xff, 0x69, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x21, 0x22, 0x22, 0x21, 0x01, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t lightbulb = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 12,
|
||||
.header.h = 20,
|
||||
.data_size = 240,
|
||||
.data = lightbulb_map,
|
||||
};
|
230
Platformio/src/device_keyboard_ble/device_keyboard_ble.cpp
Normal file
230
Platformio/src/device_keyboard_ble/device_keyboard_ble.cpp
Normal file
|
@ -0,0 +1,230 @@
|
|||
#include <BleKeyboard.h>
|
||||
#include "commandHandler.h"
|
||||
#include "device_keyboard_ble/device_keyboard_ble.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "hardware/battery.h"
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_BLE
|
||||
|
||||
BleKeyboard bleKeyboard("OMOTE Keyboard", "CoretechR");
|
||||
|
||||
void register_device_keyboard_ble() {
|
||||
commands[KEYBOARD_BLE_UP] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_UP});
|
||||
commands[KEYBOARD_BLE_DOWN] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_DOWN});
|
||||
commands[KEYBOARD_BLE_RIGHT] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_RIGHT});
|
||||
commands[KEYBOARD_BLE_LEFT] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_LEFT});
|
||||
commands[KEYBOARD_BLE_SELECT] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_SELECT});
|
||||
commands[KEYBOARD_BLE_SENDSTRING] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_SENDSTRING}); // payload must be set when calling commandHandler
|
||||
commands[KEYBOARD_BLE_BACK] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_BACK});
|
||||
commands[KEYBOARD_BLE_HOME] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_HOME});
|
||||
commands[KEYBOARD_BLE_MENU] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_MENU});
|
||||
commands[KEYBOARD_BLE_SCAN_PREVIOUS_TRACK] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_SCAN_PREVIOUS_TRACK});
|
||||
commands[KEYBOARD_BLE_REWIND_LONG] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_REWIND_LONG});
|
||||
commands[KEYBOARD_BLE_REWIND] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_REWIND});
|
||||
commands[KEYBOARD_BLE_PLAYPAUSE] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_PLAYPAUSE});
|
||||
commands[KEYBOARD_BLE_FASTFORWARD] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_FASTFORWARD});
|
||||
commands[KEYBOARD_BLE_FASTFORWARD_LONG] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_FASTFORWARD_LONG});
|
||||
commands[KEYBOARD_BLE_SCAN_NEXT_TRACK] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_SCAN_NEXT_TRACK});
|
||||
commands[KEYBOARD_BLE_MUTE] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_MUTE});
|
||||
commands[KEYBOARD_BLE_VOLUME_INCREMENT] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_VOLUME_INCREMENT});
|
||||
commands[KEYBOARD_BLE_VOLUME_DECREMENT] = makeCommandData(BLE_KEYBOARD, {KEYBOARD_BLE_VOLUME_DECREMENT});
|
||||
|
||||
bleKeyboard.begin();
|
||||
}
|
||||
|
||||
// if bluetooth is in pairing mode (pairing mode is always on, if not connected), but not connected, then blink
|
||||
unsigned long blinkBluetoothLabelLastChange = millis();
|
||||
bool blinkBluetoothLabelIsOn = false;
|
||||
|
||||
void update_keyboard_ble_status() {
|
||||
if (bleKeyboard.isConnected()) {
|
||||
lv_label_set_text(BluetoothLabel, LV_SYMBOL_BLUETOOTH);
|
||||
bleKeyboard.setBatteryLevel(battery_percentage);
|
||||
|
||||
} else {
|
||||
if(millis() - blinkBluetoothLabelLastChange >= 1000){
|
||||
blinkBluetoothLabelIsOn = !blinkBluetoothLabelIsOn;
|
||||
if (blinkBluetoothLabelIsOn) {
|
||||
lv_label_set_text(BluetoothLabel, LV_SYMBOL_BLUETOOTH);
|
||||
} else {
|
||||
lv_label_set_text(BluetoothLabel, "");
|
||||
}
|
||||
blinkBluetoothLabelLastChange = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_ble_write(uint8_t c) {
|
||||
bleKeyboard.write(c);
|
||||
}
|
||||
|
||||
void keyboard_ble_press(uint8_t c) {
|
||||
bleKeyboard.press(c);
|
||||
bleKeyboard.release(c);
|
||||
}
|
||||
|
||||
void keyboard_ble_longpress(uint8_t c) {
|
||||
bleKeyboard.press(c);
|
||||
delay(1000);
|
||||
bleKeyboard.release(c);
|
||||
}
|
||||
|
||||
void keyboard_ble_home() {
|
||||
bleKeyboard.press(KEY_LEFT_ALT);
|
||||
bleKeyboard.press(KEY_ESC);
|
||||
bleKeyboard.releaseAll();
|
||||
}
|
||||
|
||||
void keyboard_ble_sendString(const String &s) {
|
||||
bleKeyboard.print(s);
|
||||
}
|
||||
|
||||
void consumerControl_ble_write(const MediaKeyReport value) {
|
||||
bleKeyboard.write(value);
|
||||
}
|
||||
|
||||
void consumerControl_ble_press(const MediaKeyReport value) {
|
||||
bleKeyboard.press(value);
|
||||
bleKeyboard.release(value);
|
||||
}
|
||||
|
||||
void consumerControl_ble_longpress(const MediaKeyReport value) {
|
||||
bleKeyboard.press(value);
|
||||
delay(1000);
|
||||
bleKeyboard.release(value);
|
||||
}
|
||||
|
||||
void keyboard_ble_executeCommand(std::string command, std::string additionalPayload) {
|
||||
bool doLog = false;
|
||||
|
||||
if (doLog) {
|
||||
if (bleKeyboard.isConnected()) {
|
||||
Serial.println("BLE keyboard connected, could send key");
|
||||
} else {
|
||||
Serial.println("BLE keyboard NOT connected, cannot send key");
|
||||
}
|
||||
}
|
||||
|
||||
if (command == KEYBOARD_BLE_UP) {
|
||||
if (doLog) {Serial.printf("UP received\r\n");}
|
||||
keyboard_ble_write(KEY_UP_ARROW);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_DOWN) {
|
||||
if (doLog) {Serial.printf("DOWN received\r\n");}
|
||||
keyboard_ble_write(KEY_DOWN_ARROW);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_RIGHT) {
|
||||
if (doLog) {Serial.printf("RIGHT received\r\n");}
|
||||
keyboard_ble_write(KEY_RIGHT_ARROW);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_LEFT) {
|
||||
if (doLog) {Serial.printf("LEFT received\r\n");}
|
||||
keyboard_ble_write(KEY_LEFT_ARROW);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_SELECT) {
|
||||
if (doLog) {Serial.printf("SELECT received\r\n");}
|
||||
keyboard_ble_write(KEY_RETURN);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_SENDSTRING) {
|
||||
if (doLog) {Serial.printf("SENDSTRING received\r\n");}
|
||||
if (additionalPayload != "") {
|
||||
keyboard_ble_sendString(additionalPayload.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if (command == KEYBOARD_BLE_BACK) {
|
||||
if (doLog) {Serial.printf("BACK received\r\n");}
|
||||
// test which one works best for your device
|
||||
// keyboard_ble_write(KEY_ESC);
|
||||
consumerControl_ble_write(KEY_MEDIA_WWW_BACK);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_HOME) {
|
||||
if (doLog) {Serial.printf("HOME received\r\n");}
|
||||
// test which one works best for your device
|
||||
// keyboard_ble_home();
|
||||
consumerControl_ble_write(KEY_MEDIA_WWW_HOME);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_MENU) {
|
||||
if (doLog) {Serial.printf("MENU received\r\n");}
|
||||
keyboard_ble_write(0xED); // 0xDA + 13 = 0xED
|
||||
|
||||
|
||||
|
||||
// for more consumerControl codes see
|
||||
// https://github.com/espressif/arduino-esp32/blob/master/libraries/USB/src/USBHIDConsumerControl.h
|
||||
// https://github.com/adafruit/Adafruit_CircuitPython_HID/blob/main/adafruit_hid/consumer_control_code.py
|
||||
} else if (command == KEYBOARD_BLE_SCAN_PREVIOUS_TRACK) {
|
||||
if (doLog) {Serial.printf("SCAN_PREVIOUS_TRACK received\r\n");}
|
||||
consumerControl_ble_write(KEY_MEDIA_PREVIOUS_TRACK);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_REWIND_LONG) {
|
||||
if (doLog) {Serial.printf("REWIND_LONG received\r\n");}
|
||||
//keyboard_ble_longpress(KEY_LEFT_ARROW);
|
||||
consumerControl_ble_longpress(KEY_MEDIA_REWIND);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_REWIND) {
|
||||
if (doLog) {Serial.printf("REWIND received\r\n");}
|
||||
//keyboard_ble_write(KEY_LEFT_ARROW);
|
||||
consumerControl_ble_write(KEY_MEDIA_REWIND);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_PLAYPAUSE) {
|
||||
if (doLog) {Serial.printf("PLAYPAUSE received\r\n");}
|
||||
consumerControl_ble_write(KEY_MEDIA_PLAY_PAUSE);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_FASTFORWARD) {
|
||||
if (doLog) {Serial.printf("FASTFORWARD received\r\n");}
|
||||
//keyboard_ble_write(KEY_RIGHT_ARROW);
|
||||
consumerControl_ble_write(KEY_MEDIA_FASTFORWARD);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_FASTFORWARD_LONG) {
|
||||
if (doLog) {Serial.printf("FASTFORWARD_LONG received\r\n");}
|
||||
//keyboard_ble_longpress(KEY_RIGHT_ARROW);
|
||||
consumerControl_ble_longpress(KEY_MEDIA_FASTFORWARD);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_SCAN_NEXT_TRACK) {
|
||||
if (doLog) {Serial.printf("SCAN_NEXT_TRACK received\r\n");}
|
||||
consumerControl_ble_write(KEY_MEDIA_NEXT_TRACK);
|
||||
|
||||
|
||||
|
||||
} else if (command == KEYBOARD_BLE_MUTE) {
|
||||
if (doLog) {Serial.printf("MUTE received\r\n");}
|
||||
consumerControl_ble_write(KEY_MEDIA_MUTE);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_VOLUME_INCREMENT) {
|
||||
if (doLog) {Serial.printf("VOLUME_INCREMENT received\r\n");}
|
||||
consumerControl_ble_write(KEY_MEDIA_VOLUME_UP);
|
||||
|
||||
} else if (command == KEYBOARD_BLE_VOLUME_DECREMENT) {
|
||||
if (doLog) {Serial.printf("VOLUME_DECREMENT received\r\n");}
|
||||
consumerControl_ble_write(KEY_MEDIA_VOLUME_DOWN);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
const MediaKeyReport KEY_MEDIA_NEXT_TRACK = {1, 0};
|
||||
const MediaKeyReport KEY_MEDIA_PREVIOUS_TRACK = {2, 0};
|
||||
const MediaKeyReport KEY_MEDIA_STOP = {4, 0};
|
||||
const MediaKeyReport KEY_MEDIA_PLAY_PAUSE = {8, 0};
|
||||
const MediaKeyReport KEY_MEDIA_MUTE = {16, 0};
|
||||
const MediaKeyReport KEY_MEDIA_VOLUME_UP = {32, 0};
|
||||
const MediaKeyReport KEY_MEDIA_VOLUME_DOWN = {64, 0};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_HOME = {128, 0};
|
||||
const MediaKeyReport KEY_MEDIA_LOCAL_MACHINE_BROWSER = {0, 1}; // Opens "My Computer" on Windows
|
||||
// original from BLE-Keyboard
|
||||
// const MediaKeyReport KEY_MEDIA_CALCULATOR = {0, 2};
|
||||
// changed for usage in OMOTE
|
||||
const MediaKeyReport KEY_MEDIA_FASTFORWARD = {0, 2};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_BOOKMARKS = {0, 4};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_SEARCH = {0, 8};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_STOP = {0, 16};
|
||||
const MediaKeyReport KEY_MEDIA_WWW_BACK = {0, 32};
|
||||
const MediaKeyReport KEY_MEDIA_CONSUMER_CONTROL_CONFIGURATION = {0, 64}; // Media Selection
|
||||
// original from BLE-Keyboard
|
||||
// const MediaKeyReport KEY_MEDIA_EMAIL_READER = {0, 128};
|
||||
// changed for usage in OMOTE
|
||||
const MediaKeyReport KEY_MEDIA_REWIND = {0, 128};
|
||||
*/
|
47
Platformio/src/device_keyboard_ble/device_keyboard_ble.h
Normal file
47
Platformio/src/device_keyboard_ble/device_keyboard_ble.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef __DEVICE_KEYBOARD_BLE_H__
|
||||
#define __DEVICE_KEYBOARD_BLE_H__
|
||||
|
||||
// Advertising is started automatically.
|
||||
// As soon as a device is connected, a small indicator in the top left corner of the screen will appear
|
||||
|
||||
#define ENABLE_KEYBOARD_BLE // Comment out to disable BLE
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_BLE
|
||||
|
||||
#include "commandHandler.h"
|
||||
|
||||
#if defined(ENABLE_KEYBOARD_BLE) && !defined(ENABLE_BLUETOOTH)
|
||||
static_assert(false, "You have to use \"#define ENABLE_BLUETOOTH\" in \"commandHandler.h\" when having \"#define ENABLE_KEYBOARD_BLE\"");
|
||||
#endif
|
||||
|
||||
#include <BleKeyboard.h>
|
||||
|
||||
#define KEYBOARD_BLE_UP "Keyboard_ble_up"
|
||||
#define KEYBOARD_BLE_DOWN "Keyboard_ble_down"
|
||||
#define KEYBOARD_BLE_RIGHT "Keyboard_ble_right"
|
||||
#define KEYBOARD_BLE_LEFT "Keyboard_ble_left"
|
||||
#define KEYBOARD_BLE_SELECT "Keyboard_ble_select"
|
||||
#define KEYBOARD_BLE_SENDSTRING "Keyboard_ble_sendstring"
|
||||
#define KEYBOARD_BLE_BACK "Keyboard_ble_back"
|
||||
#define KEYBOARD_BLE_HOME "Keyboard_ble_home"
|
||||
#define KEYBOARD_BLE_MENU "Keyboard_ble_menu"
|
||||
#define KEYBOARD_BLE_SCAN_PREVIOUS_TRACK "Keyboard_ble_scan_previous_track"
|
||||
#define KEYBOARD_BLE_REWIND_LONG "Keyboard_ble_rewind_long"
|
||||
#define KEYBOARD_BLE_REWIND "Keyboard_ble_rewind"
|
||||
#define KEYBOARD_BLE_PLAYPAUSE "Keyboard_ble_playpause"
|
||||
#define KEYBOARD_BLE_FASTFORWARD "Keyboard_ble_fastforward"
|
||||
#define KEYBOARD_BLE_FASTFORWARD_LONG "Keyboard_ble_fastforward_long"
|
||||
#define KEYBOARD_BLE_SCAN_NEXT_TRACK "Keyboard_ble_scan_next_track"
|
||||
#define KEYBOARD_BLE_MUTE "Keyboard_ble_mute"
|
||||
#define KEYBOARD_BLE_VOLUME_INCREMENT "Keyboard_ble_volume_increment"
|
||||
#define KEYBOARD_BLE_VOLUME_DECREMENT "Keyboard_ble_volume_decrement"
|
||||
|
||||
extern BleKeyboard bleKeyboard;
|
||||
|
||||
void register_device_keyboard_ble();
|
||||
void keyboard_ble_executeCommand(std::string command, std::string additionalPayload = "");
|
||||
void update_keyboard_ble_status();
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*__DEVICE_KEYBOARD_BLE_H__*/
|
28
Platformio/src/device_keyboard_mqtt/device_keyboard_mqtt.cpp
Normal file
28
Platformio/src/device_keyboard_mqtt/device_keyboard_mqtt.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "commandHandler.h"
|
||||
#include "device_keyboard_mqtt/device_keyboard_mqtt.h"
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_MQTT
|
||||
|
||||
void register_device_keyboard_mqtt() {
|
||||
commands[KEYBOARD_MQTT_UP] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/UP", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_DOWN] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/DOWN", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_RIGHT] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/RIGHT", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_LEFT] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/LEFT", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_SELECT] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/SELECT", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_SENDSTRING] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/SENDSTRING" }); // payload must be set when calling commandHandler
|
||||
commands[KEYBOARD_MQTT_BACK] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/BACK", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_HOME] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/HOME", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_MENU] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/MENU", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_SCAN_PREVIOUS_TRACK] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/SCAN_PREVIOUS_TRACK", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_REWIND_LONG] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/REWIND_LONG", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_REWIND] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/REWIND", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_PLAYPAUSE] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/PLAYPAUSE", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_FASTFORWARD] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/FASTFORWARD", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_FASTFORWARD_LONG] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/FASTFORWARD_LONG", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_SCAN_NEXT_TRACK] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/SCAN_NEXT_TRACK", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_MUTE] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/MUTE", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_VOLUME_INCREMENT] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/VOLUME_INCREMENT", "PRESS"});
|
||||
commands[KEYBOARD_MQTT_VOLUME_DECREMENT] = makeCommandData(MQTT, {"esp32_keyboard_firetv/cmnd/VOLUME_DECREMENT", "PRESS"});
|
||||
}
|
||||
|
||||
#endif
|
43
Platformio/src/device_keyboard_mqtt/device_keyboard_mqtt.h
Normal file
43
Platformio/src/device_keyboard_mqtt/device_keyboard_mqtt.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef __DEVICE_KEYBOARD_MQTT_H__
|
||||
#define __DEVICE_KEYBOARD_MQTT_H__
|
||||
|
||||
// The "MQTT keyboard" simply sends MQTT commands to a remote keyboard, which is connected via USB to a device
|
||||
// https://github.com/KlausMu/esp32-mqtt-keyboard
|
||||
|
||||
#define ENABLE_KEYBOARD_MQTT // Comment out to disable WiFi and MQTT
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_MQTT
|
||||
|
||||
// if you activate the MQTT keyboard, consider changing the mapping of the keyboard commands to the MQTT keyboard in file "commandHandler.h"
|
||||
|
||||
#include "commandHandler.h"
|
||||
|
||||
#if defined(ENABLE_KEYBOARD_MQTT) && !defined(ENABLE_WIFI_AND_MQTT)
|
||||
static_assert(false, "You have to use \"#define ENABLE_WIFI_AND_MQTT\" in \"commandHandler.h\" when having \"#define ENABLE_KEYBOARD_MQTT\"");
|
||||
#endif
|
||||
|
||||
#define KEYBOARD_MQTT_UP "Keyboard_mqtt_up"
|
||||
#define KEYBOARD_MQTT_DOWN "Keyboard_mqtt_down"
|
||||
#define KEYBOARD_MQTT_RIGHT "Keyboard_mqtt_right"
|
||||
#define KEYBOARD_MQTT_LEFT "Keyboard_mqtt_left"
|
||||
#define KEYBOARD_MQTT_SELECT "Keyboard_mqtt_select"
|
||||
#define KEYBOARD_MQTT_SENDSTRING "Keyboard_mqtt_sendstring"
|
||||
#define KEYBOARD_MQTT_BACK "Keyboard_mqtt_back"
|
||||
#define KEYBOARD_MQTT_HOME "Keyboard_mqtt_home"
|
||||
#define KEYBOARD_MQTT_MENU "Keyboard_mqtt_menu"
|
||||
#define KEYBOARD_MQTT_SCAN_PREVIOUS_TRACK "Keyboard_mqtt_scan_previous_track"
|
||||
#define KEYBOARD_MQTT_REWIND_LONG "Keyboard_mqtt_rewind_long"
|
||||
#define KEYBOARD_MQTT_REWIND "Keyboard_mqtt_rewind"
|
||||
#define KEYBOARD_MQTT_PLAYPAUSE "Keyboard_mqtt_playpause"
|
||||
#define KEYBOARD_MQTT_FASTFORWARD "Keyboard_mqtt_fastforward"
|
||||
#define KEYBOARD_MQTT_FASTFORWARD_LONG "Keyboard_mqtt_fastforward_long"
|
||||
#define KEYBOARD_MQTT_SCAN_NEXT_TRACK "Keyboard_mqtt_scan_next_track"
|
||||
#define KEYBOARD_MQTT_MUTE "Keyboard_mqtt_mute"
|
||||
#define KEYBOARD_MQTT_VOLUME_INCREMENT "Keyboard_mqtt_volume_increment"
|
||||
#define KEYBOARD_MQTT_VOLUME_DECREMENT "Keyboard_mqtt_volume_decrement"
|
||||
|
||||
void register_device_keyboard_mqtt();
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*__DEVICE_KEYBOARD_MQTT_H__*/
|
76
Platformio/src/device_samsungTV/device_samsungTV.cpp
Normal file
76
Platformio/src/device_samsungTV/device_samsungTV.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include "commandHandler.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
|
||||
void register_device_samsung() {
|
||||
// both GC and SAMSUNG work well
|
||||
|
||||
// https://github.com/natcl/studioimaginaire/blob/master/arduino_remote/ircodes.py
|
||||
commands[SAMSUNG_POWER_TOGGLE] = makeCommandData(IR_SAMSUNG, {"0xE0E040BF"});
|
||||
commands[SAMSUNG_SOURCE] = makeCommandData(IR_SAMSUNG, {"0xE0E0807F"});
|
||||
commands[SAMSUNG_HDMI] = makeCommandData(IR_SAMSUNG, {"0xE0E0D12E"});
|
||||
commands[SAMSUNG_NUM_1] = makeCommandData(IR_SAMSUNG, {"0xE0E020DF"});
|
||||
commands[SAMSUNG_NUM_2] = makeCommandData(IR_SAMSUNG, {"0xE0E0A05F"});
|
||||
commands[SAMSUNG_NUM_3] = makeCommandData(IR_SAMSUNG, {"0xE0E0609F"});
|
||||
commands[SAMSUNG_NUM_4] = makeCommandData(IR_SAMSUNG, {"0xE0E010EF"});
|
||||
commands[SAMSUNG_NUM_5] = makeCommandData(IR_SAMSUNG, {"0xE0E0906F"});
|
||||
commands[SAMSUNG_NUM_6] = makeCommandData(IR_SAMSUNG, {"0xE0E050AF"});
|
||||
commands[SAMSUNG_NUM_7] = makeCommandData(IR_SAMSUNG, {"0xE0E030CF"});
|
||||
commands[SAMSUNG_NUM_8] = makeCommandData(IR_SAMSUNG, {"0xE0E0B04F"});
|
||||
commands[SAMSUNG_NUM_9] = makeCommandData(IR_SAMSUNG, {"0xE0E0708F"});
|
||||
commands[SAMSUNG_NUM_0] = makeCommandData(IR_SAMSUNG, {"0xE0E08877"});
|
||||
commands[SAMSUNG_TTXMIX] = makeCommandData(IR_SAMSUNG, {"0xE0E034CB"});
|
||||
commands[SAMSUNG_PRECH] = makeCommandData(IR_SAMSUNG, {"0xE0E0C837"});
|
||||
commands[SAMSUNG_VOL_MINUS] = makeCommandData(IR_SAMSUNG, {"0xE0E0D02F"});
|
||||
commands[SAMSUNG_VOL_PLUS] = makeCommandData(IR_SAMSUNG, {"0xE0E0E01F"});
|
||||
commands[SAMSUNG_MUTE_TOGGLE] = makeCommandData(IR_SAMSUNG, {"0xE0E0F00F"});
|
||||
commands[SAMSUNG_CHLIST] = makeCommandData(IR_SAMSUNG, {"0xE0E0D629"});
|
||||
commands[SAMSUNG_CHANNEL_UP] = makeCommandData(IR_SAMSUNG, {"0xE0E048B7"});
|
||||
commands[SAMSUNG_CHANNEL_DOWN] = makeCommandData(IR_SAMSUNG, {"0xE0E008F7"});
|
||||
commands[SAMSUNG_MENU] = makeCommandData(IR_SAMSUNG, {"0xE0E058A7"});
|
||||
commands[SAMSUNG_APPS] = makeCommandData(IR_SAMSUNG, {"0xE0E09E61"});
|
||||
commands[SAMSUNG_GUIDE] = makeCommandData(IR_SAMSUNG, {"0xE0E0F20D"});
|
||||
commands[SAMSUNG_TOOLS] = makeCommandData(IR_SAMSUNG, {"0xE0E0D22D"});
|
||||
commands[SAMSUNG_INFO] = makeCommandData(IR_SAMSUNG, {"0xE0E0F807"});
|
||||
commands[SAMSUNG_UP] = makeCommandData(IR_SAMSUNG, {"0xE0E006F9"});
|
||||
commands[SAMSUNG_DOWN] = makeCommandData(IR_SAMSUNG, {"0xE0E08679"});
|
||||
commands[SAMSUNG_LEFT] = makeCommandData(IR_SAMSUNG, {"0xE0E0A659"});
|
||||
commands[SAMSUNG_RIGHT] = makeCommandData(IR_SAMSUNG, {"0xE0E046B9"});
|
||||
commands[SAMSUNG_SELECT] = makeCommandData(IR_SAMSUNG, {"0xE0E016E9"});
|
||||
commands[SAMSUNG_RETURN] = makeCommandData(IR_SAMSUNG, {"0xE0E01AE5"});
|
||||
commands[SAMSUNG_EXIT] = makeCommandData(IR_SAMSUNG, {"0xE0E0B44B"});
|
||||
commands[SAMSUNG_KEY_A] = makeCommandData(IR_SAMSUNG, {"0xE0E036C9"});
|
||||
commands[SAMSUNG_KEY_B] = makeCommandData(IR_SAMSUNG, {"0xE0E028D7"});
|
||||
commands[SAMSUNG_KEY_C] = makeCommandData(IR_SAMSUNG, {"0xE0E0A857"});
|
||||
commands[SAMSUNG_KEY_D] = makeCommandData(IR_SAMSUNG, {"0xE0E06897"});
|
||||
commands[SAMSUNG_FAMILYSTORY] = makeCommandData(IR_SAMSUNG, {"0xE0E0639C"});
|
||||
commands[SAMSUNG_SEARCH] = makeCommandData(IR_SAMSUNG, {"0xE0E0CE31"});
|
||||
commands[SAMSUNG_DUALI_II] = makeCommandData(IR_SAMSUNG, {"0xE0E000FF"});
|
||||
commands[SAMSUNG_SUPPORT] = makeCommandData(IR_SAMSUNG, {"0xE0E0FC03"});
|
||||
commands[SAMSUNG_PSIZE] = makeCommandData(IR_SAMSUNG, {"0xE0E07C83"});
|
||||
commands[SAMSUNG_ADSUBT] = makeCommandData(IR_SAMSUNG, {"0xE0E0A45B"});
|
||||
commands[SAMSUNG_REWIND] = makeCommandData(IR_SAMSUNG, {"0xE0E0A25D"});
|
||||
commands[SAMSUNG_PAUSE] = makeCommandData(IR_SAMSUNG, {"0xE0E052AD"});
|
||||
commands[SAMSUNG_FASTFORWARD] = makeCommandData(IR_SAMSUNG, {"0xE0E012ED"});
|
||||
commands[SAMSUNG_RECORD] = makeCommandData(IR_SAMSUNG, {"0xE0E0926D"});
|
||||
commands[SAMSUNG_PLAY] = makeCommandData(IR_SAMSUNG, {"0xE0E0E21D"});
|
||||
commands[SAMSUNG_STOP] = makeCommandData(IR_SAMSUNG, {"0xE0E0629D"});
|
||||
commands[SAMSUNG_POWER_OFF] = makeCommandData(IR_SAMSUNG, {"0xE0E019E6"});
|
||||
commands[SAMSUNG_POWER_ON] = makeCommandData(IR_SAMSUNG, {"0xE0E09966"});
|
||||
commands[SAMSUNG_INPUT_HDMI_1] = makeCommandData(IR_SAMSUNG, {"0xE0E09768"});
|
||||
commands[SAMSUNG_INPUT_HDMI_2] = makeCommandData(IR_SAMSUNG, {"0xE0E07D82"});
|
||||
commands[SAMSUNG_INPUT_HDMI_3] = makeCommandData(IR_SAMSUNG, {"0xE0E043BC"});
|
||||
commands[SAMSUNG_INPUT_HDMI_4] = makeCommandData(IR_SAMSUNG, {"0xE0E0A35C"});
|
||||
commands[SAMSUNG_INPUT_COMPONENT] = makeCommandData(IR_SAMSUNG, {"0xE0E0619E"});
|
||||
commands[SAMSUNG_INPUT_TV] = makeCommandData(IR_SAMSUNG, {"0xE0E0D827"});
|
||||
// unknown commands. Not on my remote
|
||||
// commands[-] = makeCommandData(IR_SAMSUNG, {"0xE0E0C43B"});
|
||||
// commands[favorite_channel] = makeCommandData(IR_SAMSUNG, {"0xE0E022DD"});
|
||||
|
||||
// GC also works well
|
||||
//commands[SAMSUNG_POWER_TOGGLE] = makeCommandData(IR_GC, {"38000,1,1,170,170,20,63,20,63,20,63,20,20,20,20,20,20,20,20,20,20,20,63,20,63,20,63,20,20,20,20,20,20,20,20,20,20,20,20,20,63,20,20,20,20,20,20,20,20,20,20,20,20,20,63,20,20,20,63,20,63,20,63,20,63,20,63,20,63,20,1798"});
|
||||
//commands[SAMSUNG_POWER_OFF] = makeCommandData(IR_GC, {"38000,1,1,173,173,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,65,21,65,21,21,21,21,21,65,21,65,21,65,21,65,21,21,21,21,21,65,21,65,21,21,21,1832"});
|
||||
//commands[SAMSUNG_POWER_ON] = makeCommandData(IR_GC, {"38000,1,1,172,172,22,64,22,64,22,64,22,21,22,21,22,21,22,21,22,21,22,64,22,64,22,64,22,21,22,21,22,21,22,21,22,21,22,64,22,21,22,21,22,64,22,64,22,21,22,21,22,64,22,21,22,64,22,64,22,21,22,21,22,64,22,64,22,21,22,1820"});
|
||||
//commands[SAMSUNG_INPUT_HDMI_1] = makeCommandData(IR_GC, {"38000,1,1,173,173,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,65,21,21,21,21,21,65,21,21,21,65,21,65,21,65,21,21,21,65,21,65,21,21,21,65,21,21,21,21,21,21,21,1832"});
|
||||
//commands[SAMSUNG_INPUT_HDMI_2] = makeCommandData(IR_GC, {"38000,1,1,173,173,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,21,21,65,21,65,21,65,21,65,21,65,21,21,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,65,21,21,21,1832"});
|
||||
//commands[SAMSUNG_TV] = makeCommandData(IR_GC, {"38000,1,1,172,172,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,21,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,21,21,64,21,64,21,64,21,1673"});
|
||||
}
|
64
Platformio/src/device_samsungTV/device_samsungTV.h
Normal file
64
Platformio/src/device_samsungTV/device_samsungTV.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#ifndef __DEVICE_SAMSUNG_H__
|
||||
#define __DEVICE_SAMSUNG_H__
|
||||
|
||||
#define SAMSUNG_POWER_TOGGLE "Samsung_power_toggle"
|
||||
#define SAMSUNG_SOURCE "Samsung_source"
|
||||
#define SAMSUNG_HDMI "Samsung_hdmi"
|
||||
#define SAMSUNG_NUM_1 "Samsung_num_1"
|
||||
#define SAMSUNG_NUM_2 "Samsung_num_2"
|
||||
#define SAMSUNG_NUM_3 "Samsung_num_3"
|
||||
#define SAMSUNG_NUM_4 "Samsung_num_4"
|
||||
#define SAMSUNG_NUM_5 "Samsung_num_5"
|
||||
#define SAMSUNG_NUM_6 "Samsung_num_6"
|
||||
#define SAMSUNG_NUM_7 "Samsung_num_7"
|
||||
#define SAMSUNG_NUM_8 "Samsung_num_8"
|
||||
#define SAMSUNG_NUM_9 "Samsung_num_9"
|
||||
#define SAMSUNG_NUM_0 "Samsung_num_0"
|
||||
#define SAMSUNG_TTXMIX "Samsung_ttxmix"
|
||||
#define SAMSUNG_PRECH "Samsung_prech"
|
||||
#define SAMSUNG_VOL_MINUS "Samsung_vol_minus"
|
||||
#define SAMSUNG_VOL_PLUS "Samsung_vol_plus"
|
||||
#define SAMSUNG_MUTE_TOGGLE "Samsung_mute_toggle"
|
||||
#define SAMSUNG_CHLIST "Samsung_chlist"
|
||||
#define SAMSUNG_CHANNEL_UP "Samsung_channel_up"
|
||||
#define SAMSUNG_CHANNEL_DOWN "Samsung_channel_down"
|
||||
#define SAMSUNG_MENU "Samsung_menu"
|
||||
#define SAMSUNG_APPS "Samsung_apps"
|
||||
#define SAMSUNG_GUIDE "Samsung_guide"
|
||||
#define SAMSUNG_TOOLS "Samsung_tools"
|
||||
#define SAMSUNG_INFO "Samsung_info"
|
||||
#define SAMSUNG_UP "Samsung_up"
|
||||
#define SAMSUNG_DOWN "Samsung_down"
|
||||
#define SAMSUNG_LEFT "Samsung_left"
|
||||
#define SAMSUNG_RIGHT "Samsung_right"
|
||||
#define SAMSUNG_SELECT "Samsung_select"
|
||||
#define SAMSUNG_RETURN "Samsung_return"
|
||||
#define SAMSUNG_EXIT "Samsung_exit"
|
||||
#define SAMSUNG_KEY_A "Samsung_key_a"
|
||||
#define SAMSUNG_KEY_B "Samsung_key_b"
|
||||
#define SAMSUNG_KEY_C "Samsung_key_c"
|
||||
#define SAMSUNG_KEY_D "Samsung_key_d"
|
||||
#define SAMSUNG_FAMILYSTORY "Samsung_familystory"
|
||||
#define SAMSUNG_SEARCH "Samsung_search"
|
||||
#define SAMSUNG_DUALI_II "Samsung_duali-ii"
|
||||
#define SAMSUNG_SUPPORT "Samsung_support"
|
||||
#define SAMSUNG_PSIZE "Samsung_psize"
|
||||
#define SAMSUNG_ADSUBT "Samsung_adsubt"
|
||||
#define SAMSUNG_REWIND "Samsung_rewind"
|
||||
#define SAMSUNG_PAUSE "Samsung_pause"
|
||||
#define SAMSUNG_FASTFORWARD "Samsung_fastforward"
|
||||
#define SAMSUNG_RECORD "Samsung_record"
|
||||
#define SAMSUNG_PLAY "Samsung_play"
|
||||
#define SAMSUNG_STOP "Samsung_stop"
|
||||
#define SAMSUNG_POWER_OFF "Samsung_power_off"
|
||||
#define SAMSUNG_POWER_ON "Samsung_power_on"
|
||||
#define SAMSUNG_INPUT_HDMI_1 "Samsung_input_hdmi_1"
|
||||
#define SAMSUNG_INPUT_HDMI_2 "Samsung_input_hdmi_2"
|
||||
#define SAMSUNG_INPUT_HDMI_3 "Samsung_input_hdmi_3"
|
||||
#define SAMSUNG_INPUT_HDMI_4 "Samsung_input_hdmi_4"
|
||||
#define SAMSUNG_INPUT_COMPONENT "Samsung_input_component"
|
||||
#define SAMSUNG_INPUT_TV "Samsung_input_tv"
|
||||
|
||||
void register_device_samsung();
|
||||
|
||||
#endif /*__DEVICE_SAMSUNG_H__*/
|
11
Platformio/src/device_smarthome/device_smarthome.cpp
Normal file
11
Platformio/src/device_smarthome/device_smarthome.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "commandHandler.h"
|
||||
#include "device_smarthome/device_smarthome.h"
|
||||
|
||||
void register_device_smarthome() {
|
||||
#ifdef ENABLE_KEYBOARD_MQTT
|
||||
commands[SMARTHOME_MQTT_BULB1_SET] = makeCommandData(MQTT, {"bulb1_set" }); // payload must be set when calling commandHandler
|
||||
commands[SMARTHOME_MQTT_BULB2_SET] = makeCommandData(MQTT, {"bulb2_set" }); // payload must be set when calling commandHandler
|
||||
commands[SMARTHOME_MQTT_BULB1_BRIGHTNESS_SET] = makeCommandData(MQTT, {"bulb1_setbrightness" }); // payload must be set when calling commandHandler
|
||||
commands[SMARTHOME_MQTT_BULB2_BRIGHTNESS_SET] = makeCommandData(MQTT, {"bulb2_setbrightness" }); // payload must be set when calling commandHandler
|
||||
#endif
|
||||
}
|
11
Platformio/src/device_smarthome/device_smarthome.h
Normal file
11
Platformio/src/device_smarthome/device_smarthome.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef __DEVICE_SMARTHOME_H__
|
||||
#define __DEVICE_SMARTHOME_H__
|
||||
|
||||
#define SMARTHOME_MQTT_BULB1_SET "Smarthome_mqtt_bulb1_set"
|
||||
#define SMARTHOME_MQTT_BULB2_SET "Smarthome_mqtt_bulb2_set"
|
||||
#define SMARTHOME_MQTT_BULB1_BRIGHTNESS_SET "Smarthome_mqtt_bulb1_brightness_set"
|
||||
#define SMARTHOME_MQTT_BULB2_BRIGHTNESS_SET "Smarthome_mqtt_bulb2_brightness_set"
|
||||
|
||||
void register_device_smarthome();
|
||||
|
||||
#endif /*__DEVICE_SMARTHOME_H__*/
|
146
Platformio/src/device_smarthome/gui_smarthome.cpp
Normal file
146
Platformio/src/device_smarthome/gui_smarthome.cpp
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include <string>
|
||||
#include <lvgl.h>
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/guiRegistry.h"
|
||||
#include "hardware/tft.h"
|
||||
#include "device_smarthome/device_smarthome.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
// LVGL declarations
|
||||
LV_IMG_DECLARE(lightbulb);
|
||||
|
||||
// Smart Home Toggle Event handler
|
||||
static void smartHomeToggle_event_cb(lv_event_t * e){
|
||||
std::string payload;
|
||||
if (lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED)) payload = "true";
|
||||
else payload = "false";
|
||||
// Publish an MQTT message based on the event user data
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
if((int)e->user_data == 1) executeCommand(SMARTHOME_MQTT_BULB1_SET, payload);
|
||||
if((int)e->user_data == 2) executeCommand(SMARTHOME_MQTT_BULB2_SET, payload);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Smart Home Slider Event handler
|
||||
static void smartHomeSlider_event_cb(lv_event_t * e){
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
char payload[8];
|
||||
dtostrf(lv_slider_get_value(slider), 1, 2, payload);
|
||||
std::string payload_str(payload);
|
||||
// Publish an MQTT message based on the event user data
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
if((int)e->user_data == 1) executeCommand(SMARTHOME_MQTT_BULB1_BRIGHTNESS_SET, payload);
|
||||
if((int)e->user_data == 2) executeCommand(SMARTHOME_MQTT_BULB2_BRIGHTNESS_SET, payload);
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_gui_tab_smarthome(lv_obj_t* tabview) {
|
||||
|
||||
lv_obj_t* tab = lv_tabview_add_tab(tabview, "Smart Home");
|
||||
|
||||
// Add content to the smart home tab (4)
|
||||
lv_obj_set_layout(tab, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(tab, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(tab, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
// Add a label, then a box for the light controls
|
||||
lv_obj_t* menuLabel = lv_label_create(tab);
|
||||
lv_label_set_text(menuLabel, "Living Room");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* bulbIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(bulbIcon, &lightbulb);
|
||||
lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Floor Lamp");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleA = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleA, 40, 22);
|
||||
lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleA, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
|
||||
lv_obj_t* slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
|
||||
// Add another menu box for a second appliance
|
||||
menuBox = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
bulbIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(bulbIcon, &lightbulb);
|
||||
lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Ceiling Light");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleB = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleB, 40, 22);
|
||||
lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleB, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
|
||||
// Add another room (empty for now)
|
||||
menuLabel = lv_label_create(tab);
|
||||
lv_label_set_text(menuLabel, "Kitchen");
|
||||
|
||||
menuBox = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
}
|
||||
|
||||
void init_gui_pageIndicator_smarthome(lv_obj_t* panel) {
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Smart Home");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
}
|
||||
|
||||
void register_gui_smarthome(void){
|
||||
register_gui(& init_gui_tab_smarthome, & init_gui_pageIndicator_smarthome);
|
||||
}
|
8
Platformio/src/device_smarthome/gui_smarthome.h
Normal file
8
Platformio/src/device_smarthome/gui_smarthome.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __GUI_SMARTHOME_H__
|
||||
#define __GUI_SMARTHOME_H__
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
void register_gui_smarthome(void);
|
||||
|
||||
#endif /*__GUI_SMARTHOME_H__*/
|
43
Platformio/src/device_smarthome/gui_smarthome_assets.c
Normal file
43
Platformio/src/device_smarthome/gui_smarthome_assets.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include <lvgl.h>
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_LIGHTBULB
|
||||
#define LV_ATTRIBUTE_IMG_LIGHTBULB
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LIGHTBULB uint8_t lightbulb_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x16, 0x95, 0xee, 0xff, 0xff, 0xee, 0x94, 0x15, 0x00, 0x00,
|
||||
0x00, 0x27, 0xe3, 0xff, 0xcc, 0x8d, 0x8d, 0xcd, 0xff, 0xe1, 0x26, 0x00,
|
||||
0x07, 0xd9, 0xfa, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xfa, 0xd7, 0x06,
|
||||
0x65, 0xff, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xff, 0x63,
|
||||
0xb1, 0xf8, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf8, 0xaf,
|
||||
0xcc, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xcd,
|
||||
0xb1, 0xf5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf1, 0xbd,
|
||||
0x73, 0xff, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xff, 0x74,
|
||||
0x0b, 0xd5, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfb, 0xd9, 0x0b,
|
||||
0x00, 0x24, 0xef, 0xdc, 0x01, 0x00, 0x00, 0x01, 0xdd, 0xee, 0x24, 0x00,
|
||||
0x00, 0x00, 0x83, 0xff, 0x30, 0x00, 0x00, 0x30, 0xff, 0x81, 0x00, 0x00,
|
||||
0x00, 0x00, 0x12, 0x6c, 0x06, 0x00, 0x00, 0x06, 0x6c, 0x12, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0x25, 0x00, 0x00,
|
||||
0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0x25, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1c, 0x76, 0x77, 0x77, 0x76, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x69, 0xff, 0xff, 0xff, 0xff, 0x69, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x21, 0x22, 0x22, 0x21, 0x01, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t lightbulb = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 12,
|
||||
.header.h = 20,
|
||||
.data_size = 240,
|
||||
.data = lightbulb_map,
|
||||
};
|
44
Platformio/src/device_yamahaAmp/device_yamahaAmp.cpp
Normal file
44
Platformio/src/device_yamahaAmp/device_yamahaAmp.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "commandHandler.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
|
||||
void register_device_yamaha() {
|
||||
commands[YAMAHA_INPUT_DVD] = makeCommandData(IR_NEC, {"0x5EA1837C"});
|
||||
commands[YAMAHA_INPUT_DTV] = makeCommandData(IR_NEC, {"0x5EA12AD5"});
|
||||
commands[YAMAHA_INPUT_VCR] = makeCommandData(IR_NEC, {"0x5EA1F00F"});
|
||||
commands[YAMAHA_POWER_TOGGLE] = makeCommandData(IR_NEC, {"0x5EA1F807"});
|
||||
commands[YAMAHA_INPUT_CD] = makeCommandData(IR_NEC, {"0x5EA1A857"});
|
||||
commands[YAMAHA_INPUT_MD] = makeCommandData(IR_NEC, {"0x5EA1936C"});
|
||||
commands[YAMAHA_INPUT_VAUX] = makeCommandData(IR_NEC, {"0x5EA1AA55"});
|
||||
commands[YAMAHA_MULTICHANNEL] = makeCommandData(IR_NEC, {"0x5EA1E11E"});
|
||||
commands[YAMAHA_INPUT_TUNER] = makeCommandData(IR_NEC, {"0x5EA16897"});
|
||||
commands[YAMAHA_PRESETGROUP] = makeCommandData(IR_NEC, {"0x5EA148B7"});
|
||||
commands[YAMAHA_PRESETSTATION_MINUS] = makeCommandData(IR_NEC, {"0x5EA18877"});
|
||||
commands[YAMAHA_PRESETSTATION_PLUS] = makeCommandData(IR_NEC, {"0x5EA108F7"});
|
||||
commands[YAMAHA_STANDARD] = makeCommandData(IR_NEC, {"0x5EA109F6"});
|
||||
commands[YAMAHA_5CHSTEREO] = makeCommandData(IR_NEC, {"0x5EA1E916"});
|
||||
commands[YAMAHA_NIGHT] = makeCommandData(IR_NEC, {"0x5EA1A956"});
|
||||
commands[YAMAHA_SLEEP] = makeCommandData(IR_NEC, {"0x5EA1EA15"});
|
||||
commands[YAMAHA_TEST] = makeCommandData(IR_NEC, {"0x5EA1A15E"});
|
||||
commands[YAMAHA_STRAIGHT] = makeCommandData(IR_NEC, {"0x5EA16A95"});
|
||||
commands[YAMAHA_VOL_MINUS] = makeCommandData(IR_NEC, {"0x5EA1D827"});
|
||||
commands[YAMAHA_VOL_PLUS] = makeCommandData(IR_NEC, {"0x5EA158A7"});
|
||||
commands[YAMAHA_PROG_MINUS] = makeCommandData(IR_NEC, {"0x5EA19A65"});
|
||||
commands[YAMAHA_PROG_PLUS] = makeCommandData(IR_NEC, {"0x5EA11AE5"});
|
||||
commands[YAMAHA_MUTE_TOGGLE] = makeCommandData(IR_NEC, {"0x5EA138C7"});
|
||||
commands[YAMAHA_LEVEL] = makeCommandData(IR_NEC, {"0x5EA1619E"});
|
||||
commands[YAMAHA_SETMENU] = makeCommandData(IR_NEC, {"0x5EA139C6"});
|
||||
commands[YAMAHA_SETMENU_UP] = makeCommandData(IR_NEC, {"0x5EA119E6"});
|
||||
commands[YAMAHA_SETMENU_DOWN] = makeCommandData(IR_NEC, {"0x5EA19966"});
|
||||
commands[YAMAHA_SETMENU_MINUS] = makeCommandData(IR_NEC, {"0x5EA1CA35"});
|
||||
commands[YAMAHA_SETMENU_PLUS] = makeCommandData(IR_NEC, {"0x5EA14AB5"});
|
||||
commands[YAMAHA_POWER_OFF] = makeCommandData(IR_NEC, {"0x5EA17887"});
|
||||
commands[YAMAHA_POWER_ON] = makeCommandData(IR_NEC, {"0x5EA1B847"});
|
||||
|
||||
// GC seems not to work
|
||||
//commands[YAMAHA_POWER_TOGGLE] = makeCommandData(IR_GC, {"38000,1,69,341,170,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,64,21,21,21,64,21,21,21,64,21,21,21,21,21,64,21,21,21,64,21,21,21,64,21,21,21,64,21,64,21,1517,341,85,21,3655"});
|
||||
//commands[YAMAHA_POWER_OFF] = makeCommandData(IR_GC, {"38000,1,69,341,170,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,1517,341,85,21,3655"});
|
||||
//commands[YAMAHA_POWER_ON] = makeCommandData(IR_GC, {"38000,1,69,341,170,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,1517,341,85,21,3655"});
|
||||
//commands[YAMAHA_INPUT_DVD] = makeCommandData(IR_GC, {"38000,1,69,341,170,21,21,21,64,21,21,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,21,21,64,21,64,21,64,21,64,21,64,21,21,21,21,21,1517,341,85,21,3655"});
|
||||
//commands[YAMAHA_INPUT_DTV] = makeCommandData(IR_GC, {"38000,1,69,341,170,21,21,21,64,21,21,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,64,21,21,21,21,21,64,21,21,21,64,21,21,21,64,21,21,21,64,21,64,21,21,21,64,21,21,21,64,21,21,21,64,21,1517,341,85,21,3655"});
|
||||
//commands[YAMAHA_STANDARD] = makeCommandData(IR_GC, {"38000,1,69,341,170,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,64,21,64,21,64,21,64,21,64,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,1517,341,85,21,3655"});
|
||||
}
|
48
Platformio/src/device_yamahaAmp/device_yamahaAmp.h
Normal file
48
Platformio/src/device_yamahaAmp/device_yamahaAmp.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef __DEVICE_YAMAHA_H__
|
||||
#define __DEVICE_YAMAHA_H__
|
||||
|
||||
#define YAMAHA_INPUT_DVD "Yamaha_input_dvd"
|
||||
#define YAMAHA_INPUT_DTV "Yamaha_input_dtv"
|
||||
#define YAMAHA_INPUT_VCR "Yamaha_input_vcr"
|
||||
#define YAMAHA_POWER_TOGGLE "Yamaha_power_toggle"
|
||||
|
||||
#define YAMAHA_INPUT_CD "Yamaha_input_cd"
|
||||
#define YAMAHA_INPUT_MD "Yamaha_input_md"
|
||||
#define YAMAHA_INPUT_VAUX "Yamaha_input_vaux"
|
||||
#define YAMAHA_MULTICHANNEL "Yamaha_multichannel"
|
||||
|
||||
#define YAMAHA_INPUT_TUNER "Yamaha_input_tuner"
|
||||
#define YAMAHA_PRESETGROUP "Yamaha_presetgroup"
|
||||
#define YAMAHA_PRESETSTATION_MINUS "Yamaha_presetstation-"
|
||||
#define YAMAHA_PRESETSTATION_PLUS "Yamaha_presetstation+"
|
||||
|
||||
#define YAMAHA_STANDARD "Yamaha_standard"
|
||||
#define YAMAHA_5CHSTEREO "Yamaha_5chstereo"
|
||||
#define YAMAHA_NIGHT "Yamaha_night"
|
||||
#define YAMAHA_SLEEP "Yamaha_sleep"
|
||||
|
||||
#define YAMAHA_TEST "Yamaha_test"
|
||||
#define YAMAHA_STRAIGHT "Yamaha_straight"
|
||||
|
||||
#define YAMAHA_VOL_MINUS "Yamaha_vol-"
|
||||
#define YAMAHA_VOL_PLUS "Yamaha_vol+"
|
||||
|
||||
#define YAMAHA_PROG_MINUS "Yamaha_prog-"
|
||||
#define YAMAHA_PROG_PLUS "Yamaha_prog+"
|
||||
|
||||
#define YAMAHA_MUTE_TOGGLE "Yamaha_mute_toggle"
|
||||
|
||||
#define YAMAHA_LEVEL "Yamaha_level"
|
||||
#define YAMAHA_SETMENU "Yamaha_setmenu"
|
||||
|
||||
#define YAMAHA_SETMENU_UP "Yamaha_setmenu_up"
|
||||
#define YAMAHA_SETMENU_DOWN "Yamaha_setmenu_down"
|
||||
#define YAMAHA_SETMENU_MINUS "Yamaha_setmenu_-"
|
||||
#define YAMAHA_SETMENU_PLUS "Yamaha_setmenu_+"
|
||||
|
||||
#define YAMAHA_POWER_OFF "Yamaha_power_off"
|
||||
#define YAMAHA_POWER_ON "Yamaha_power_on"
|
||||
|
||||
void register_device_yamaha();
|
||||
|
||||
#endif /*__DEVICE_YAMAHA_H__*/
|
219
Platformio/src/gui_general_and_keys/guiBase.cpp
Normal file
219
Platformio/src/gui_general_and_keys/guiBase.cpp
Normal file
|
@ -0,0 +1,219 @@
|
|||
#include <lvgl.h>
|
||||
#include "hardware/tft.h"
|
||||
#include "hardware/sleep.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/guiRegistry.h"
|
||||
|
||||
lv_obj_t* panel;
|
||||
lv_color_t color_primary = lv_color_hex(0x303030); // gray
|
||||
lv_obj_t* WifiLabel = NULL;
|
||||
lv_obj_t* BluetoothLabel;
|
||||
lv_obj_t* objBattPercentage;
|
||||
lv_obj_t* objBattIcon;
|
||||
lv_obj_t* SceneLabel;
|
||||
byte currentScreen = 1; // Current Device to control (allows switching mappings between devices)
|
||||
|
||||
// LVGL declarations
|
||||
LV_IMG_DECLARE(gradientLeft);
|
||||
LV_IMG_DECLARE(gradientRight);
|
||||
|
||||
// Helper Functions -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Set the page indicator scroll position relative to the tabview scroll position
|
||||
static void store_scroll_value_event_cb(lv_event_t* e){
|
||||
float bias = (150.0 + 8.0) / 240.0;
|
||||
int offset = 240 / 2 - 150 / 2 - 8 - 50 - 3;
|
||||
lv_obj_t* screen = lv_event_get_target(e);
|
||||
lv_obj_scroll_to_x(panel, lv_obj_get_scroll_x(screen) * bias - offset, LV_ANIM_OFF);
|
||||
}
|
||||
|
||||
// Update current screen when the tabview page is changes
|
||||
static void tabview_device_event_cb(lv_event_t* e){
|
||||
currentScreen = lv_tabview_get_tab_act(lv_event_get_target(e));
|
||||
}
|
||||
|
||||
// Display flushing
|
||||
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
|
||||
uint32_t w = ( area->x2 - area->x1 + 1 );
|
||||
uint32_t h = ( area->y2 - area->y1 + 1 );
|
||||
|
||||
tft.startWrite();
|
||||
tft.setAddrWindow( area->x1, area->y1, w, h );
|
||||
tft.pushPixelsDMA( ( uint16_t * )&color_p->full, w * h);
|
||||
tft.endWrite();
|
||||
|
||||
lv_disp_flush_ready( disp );
|
||||
}
|
||||
|
||||
// Read the touchpad
|
||||
void my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data){
|
||||
// int16_t touchX, touchY;
|
||||
touchPoint = touch.getPoint();
|
||||
int16_t touchX = touchPoint.x;
|
||||
int16_t touchY = touchPoint.y;
|
||||
bool touched = false;
|
||||
if ((touchX > 0) || (touchY > 0)) {
|
||||
touched = true;
|
||||
resetStandbyTimer();
|
||||
}
|
||||
|
||||
if( !touched ){
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
else{
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
|
||||
// Set the coordinates
|
||||
data->point.x = screenWidth - touchX;
|
||||
data->point.y = screenHeight - touchY;
|
||||
|
||||
//Serial.print( "touchpoint: x" );
|
||||
//Serial.print( touchX );
|
||||
//Serial.print( " y" );
|
||||
//Serial.println( touchY );
|
||||
//tft.drawFastHLine(0, screenHeight - touchY, screenWidth, TFT_RED);
|
||||
//tft.drawFastVLine(screenWidth - touchX, 0, screenHeight, TFT_RED);
|
||||
}
|
||||
}
|
||||
|
||||
static lv_disp_draw_buf_t draw_buf;
|
||||
// static lv_color_t bufA[ screenWidth * screenHeight / 10 ];
|
||||
// static lv_color_t bufB[ screenWidth * screenHeight / 10 ];
|
||||
|
||||
void init_gui(void) {
|
||||
|
||||
// Setup LVGL ---------------------------------------------------------------------------------------------
|
||||
lv_init();
|
||||
|
||||
lv_color_t * bufA = (lv_color_t *) malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 10);
|
||||
lv_color_t * bufB = (lv_color_t *) malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 10);
|
||||
|
||||
lv_disp_draw_buf_init( &draw_buf, bufA, bufB, screenWidth * screenHeight / 10 );
|
||||
|
||||
// Initialize the display driver --------------------------------------------------------------------------
|
||||
static lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init( &disp_drv );
|
||||
disp_drv.hor_res = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.draw_buf = &draw_buf;
|
||||
lv_disp_drv_register( &disp_drv );
|
||||
|
||||
// Initialize the touchscreen driver
|
||||
static lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init( &indev_drv );
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = my_touchpad_read;
|
||||
lv_indev_drv_register( &indev_drv );
|
||||
|
||||
|
||||
// --- LVGL UI Configuration ---
|
||||
|
||||
// Set the background color -------------------------------------------------------------------------------
|
||||
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
|
||||
|
||||
// Setup a scrollable tabview for devices and settings ----------------------------------------------------
|
||||
lv_obj_t* tabview;
|
||||
tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0
|
||||
lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_size(tabview, screenWidth, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
|
||||
lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20);
|
||||
|
||||
// Add all the tabs here
|
||||
create_gui_tabs_from_gui_registry(tabview);
|
||||
|
||||
// Set current page according to the current screen
|
||||
lv_tabview_set_act(tabview, currentScreen, LV_ANIM_OFF);
|
||||
|
||||
|
||||
// Create a page indicator at the bottom ------------------------------------------------------------------
|
||||
panel = lv_obj_create(lv_scr_act());
|
||||
lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
|
||||
lv_obj_set_size(panel, screenWidth, 30);
|
||||
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
create_gui_pageIndicators_from_gui_registry(panel);
|
||||
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
||||
// Make the indicator scroll together with the tabs by creating a scroll event
|
||||
lv_obj_add_event_cb(lv_tabview_get_content(tabview), store_scroll_value_event_cb, LV_EVENT_SCROLL, NULL);
|
||||
lv_obj_add_event_cb(tabview, tabview_device_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
// Initialize scroll position for the indicator
|
||||
lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL);
|
||||
|
||||
// Style the panel background
|
||||
static lv_style_t style_btn;
|
||||
lv_style_init(&style_btn);
|
||||
lv_style_set_pad_all(&style_btn, 3);
|
||||
lv_style_set_border_width(&style_btn, 0);
|
||||
lv_style_set_bg_opa(&style_btn, LV_OPA_TRANSP);
|
||||
lv_obj_add_style(panel, &style_btn, 0);
|
||||
|
||||
// Make the indicator fade out at the sides using gradient bitmaps
|
||||
lv_obj_t* img1 = lv_img_create(lv_scr_act());
|
||||
lv_img_set_src(img1, &gradientLeft);
|
||||
lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
|
||||
lv_obj_t* img2 = lv_img_create(lv_scr_act());
|
||||
lv_img_set_src(img2, &gradientRight);
|
||||
lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
lv_obj_set_size(img2, 30, 30);
|
||||
|
||||
|
||||
// Create a status bar at the top -------------------------------------------------------------------------
|
||||
lv_obj_t* statusbar = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_size(statusbar, 240, 20);
|
||||
lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
// WiFi -------------------------------------------------------------------------
|
||||
WifiLabel = lv_label_create(statusbar);
|
||||
lv_label_set_text(WifiLabel, "");
|
||||
lv_obj_align(WifiLabel, LV_ALIGN_LEFT_MID, -8, 0);
|
||||
lv_obj_set_style_text_font(WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
// Bluetooth --------------------------------------------------------------------
|
||||
BluetoothLabel = lv_label_create(statusbar);
|
||||
lv_label_set_text(BluetoothLabel, "");
|
||||
lv_obj_align(BluetoothLabel, LV_ALIGN_LEFT_MID, 12, 0);
|
||||
lv_obj_set_style_text_font(BluetoothLabel, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
// Scene ------------------------------------------------------------------------
|
||||
SceneLabel = lv_label_create(statusbar);
|
||||
lv_label_set_text(SceneLabel, "");
|
||||
lv_obj_align(SceneLabel, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_text_font(SceneLabel, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
// Battery ----------------------------------------------------------------------
|
||||
objBattPercentage = lv_label_create(statusbar);
|
||||
lv_label_set_text(objBattPercentage, "");
|
||||
// lv_obj_align(objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0);
|
||||
lv_obj_align(objBattPercentage, LV_ALIGN_RIGHT_MID, -20, 0);
|
||||
lv_obj_set_style_text_font(objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
objBattIcon = lv_label_create(statusbar);
|
||||
lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
lv_obj_align(objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0);
|
||||
lv_obj_set_style_text_font(objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
|
||||
// --- End of LVGL configuration ---
|
||||
|
||||
}
|
||||
|
||||
void gui_loop(void) {
|
||||
lv_timer_handler();
|
||||
}
|
23
Platformio/src/gui_general_and_keys/guiBase.h
Normal file
23
Platformio/src/gui_general_and_keys/guiBase.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef __GUIBASE_H__
|
||||
#define __GUIBASE_H__
|
||||
|
||||
#include <lvgl.h>
|
||||
#include "../hardware/tft.h"
|
||||
|
||||
// LVGL declarations
|
||||
LV_IMG_DECLARE(high_brightness);
|
||||
LV_IMG_DECLARE(low_brightness);
|
||||
extern lv_obj_t* objBattPercentage;
|
||||
extern lv_obj_t* objBattIcon;
|
||||
extern lv_obj_t* SceneLabel;
|
||||
extern lv_color_t color_primary;
|
||||
|
||||
extern lv_obj_t* WifiLabel;
|
||||
extern lv_obj_t* BluetoothLabel;
|
||||
|
||||
extern byte currentScreen; // Current screen that is shown
|
||||
|
||||
void init_gui(void);
|
||||
void gui_loop(void);
|
||||
|
||||
#endif /*__GUIBASE_H__*/
|
113
Platformio/src/gui_general_and_keys/guiBase_assets.c
Normal file
113
Platformio/src/gui_general_and_keys/guiBase_assets.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include <lvgl.h>
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_GRADIENTLEFT
|
||||
#define LV_ATTRIBUTE_IMG_GRADIENTLEFT
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_GRADIENTLEFT uint8_t gradientLeft_map[] = {
|
||||
0xfa, 0xf2, 0xea, 0xe2, 0xda, 0xd1, 0xc7, 0xbe, 0xb7, 0xae, 0xa6, 0x9e, 0x95, 0x8d, 0x84, 0x7d, 0x74, 0x6c, 0x62, 0x5a, 0x51, 0x48, 0x41, 0x38, 0x2f, 0x28, 0x1f, 0x17, 0x0f, 0x07,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t gradientLeft = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 30,
|
||||
.header.h = 1,
|
||||
.data_size = 30,
|
||||
.data = gradientLeft_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_GRADIENTRIGHT
|
||||
#define LV_ATTRIBUTE_IMG_GRADIENTRIGHT
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_GRADIENTRIGHT uint8_t gradientRight_map[] = {
|
||||
0x07, 0x0f, 0x17, 0x1f, 0x28, 0x2f, 0x38, 0x41, 0x48, 0x51, 0x5a, 0x62, 0x6c, 0x74, 0x7d, 0x84, 0x8d, 0x95, 0x9e, 0xa6, 0xae, 0xb7, 0xbe, 0xc7, 0xd1, 0xda, 0xe2, 0xea, 0xf2, 0xfa,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t gradientRight = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 30,
|
||||
.header.h = 1,
|
||||
.data_size = 30,
|
||||
.data = gradientRight_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_HIGH_BRIGHTNESS
|
||||
#define LV_ATTRIBUTE_IMG_HIGH_BRIGHTNESS
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_HIGH_BRIGHTNESS uint8_t high_brightness_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbd, 0xcc, 0xbd,
|
||||
0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x0d, 0xbd, 0xcc, 0xbd,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x40, 0xd3, 0xff, 0xfe, 0xd2, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t high_brightness = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 18,
|
||||
.header.h = 18,
|
||||
.data_size = 324,
|
||||
.data = high_brightness_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_LOW_BRIGHTNESS
|
||||
#define LV_ATTRIBUTE_IMG_LOW_BRIGHTNESS
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LOW_BRIGHTNESS uint8_t low_brightness_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0x72, 0x28, 0x00, 0x00,
|
||||
0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x0b, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbc, 0x44,
|
||||
0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x11, 0x0d, 0xbc, 0x44,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x0b, 0x00, 0x40, 0xd3, 0xfe, 0xff, 0xd2, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0x72, 0x28, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t low_brightness = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 16,
|
||||
.header.h = 16,
|
||||
.data_size = 256,
|
||||
.data = low_brightness_map,
|
||||
};
|
31
Platformio/src/gui_general_and_keys/guiRegistry.cpp
Normal file
31
Platformio/src/gui_general_and_keys/guiRegistry.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <string>
|
||||
#include <list>
|
||||
#include <lvgl.h>
|
||||
#include "guiregistry.h"
|
||||
|
||||
// https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work
|
||||
struct gui_definition {
|
||||
init_gui_tab this_init_gui_tab;
|
||||
init_gui_pageIndicator this_init_gui_pageIndicator;
|
||||
};
|
||||
|
||||
std::list<gui_definition> registered_guis;
|
||||
|
||||
void register_gui(init_gui_tab a_init_gui_tab, init_gui_pageIndicator a_gui_pageIndicator) {
|
||||
registered_guis.push_back(gui_definition{a_init_gui_tab, a_gui_pageIndicator});
|
||||
|
||||
}
|
||||
|
||||
void create_gui_tabs_from_gui_registry(lv_obj_t* tabview) {
|
||||
std::list<gui_definition>::iterator it;
|
||||
for (it = registered_guis.begin(); it != registered_guis.end(); ++it) {
|
||||
it->this_init_gui_tab(tabview);
|
||||
}
|
||||
}
|
||||
|
||||
void create_gui_pageIndicators_from_gui_registry(lv_obj_t* panel) {
|
||||
std::list<gui_definition>::iterator it;
|
||||
for (it = registered_guis.begin(); it != registered_guis.end(); ++it) {
|
||||
it->this_init_gui_pageIndicator(panel);
|
||||
}
|
||||
}
|
29
Platformio/src/gui_general_and_keys/guiRegistry.h
Normal file
29
Platformio/src/gui_general_and_keys/guiRegistry.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef __GUIREGISTRY_H__
|
||||
#define __GUIREGISTRY_H__
|
||||
|
||||
/*
|
||||
If you want to create a new GUI for the touch screen, then
|
||||
- copy one of the existing GUIs, e.g. gui_numpad.cpp and gui_numpad.h
|
||||
- place the files in the right folder:
|
||||
- in folder "gui_general_and_keys" if they are of general purpose, not only for a specific device
|
||||
- in the device folder, if the GUI is specific for a certain device
|
||||
- in folder "scenes" if the GUI is intended for a specific scene
|
||||
It does not really matter where the files are placed, but doing so helps to keep a clean structure
|
||||
- rename the functions, they must not have the same name as the ones in the file you copied from
|
||||
- call "register_gui_<nameOfGUI>();" in main.cpp
|
||||
|
||||
Technically spoken, to register a GUI, you need to provide two function pointers:
|
||||
- one for creating the tab
|
||||
- one for creating the page indicator at the bottom of the tab
|
||||
*/
|
||||
#include <string>
|
||||
#include <lvgl.h>
|
||||
|
||||
typedef void (*init_gui_tab)(lv_obj_t* tabview);
|
||||
typedef void (*init_gui_pageIndicator)(lv_obj_t* tabview);
|
||||
|
||||
void register_gui(init_gui_tab a_init_gui_tab, init_gui_pageIndicator a_gui_pageIndicator);
|
||||
void create_gui_tabs_from_gui_registry(lv_obj_t* tabview);
|
||||
void create_gui_pageIndicators_from_gui_registry(lv_obj_t* panel);
|
||||
|
||||
#endif /*__GUIREGISTRY_H__*/
|
139
Platformio/src/gui_general_and_keys/gui_irReceiver.cpp
Normal file
139
Platformio/src/gui_general_and_keys/gui_irReceiver.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
#include <lvgl.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "hardware/tft.h"
|
||||
#include "hardware/sleep.h"
|
||||
#include "hardware/infrared_receiver.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/guiRegistry.h"
|
||||
|
||||
lv_obj_t* menuBoxToggle;
|
||||
lv_obj_t* menuBoxMessages;
|
||||
int16_t boxHeightDeactivated = 0;
|
||||
int16_t boxHeightActivated = 200;
|
||||
const int maxCountMessages = 15;
|
||||
lv_obj_t* irReceivedMessage[maxCountMessages];
|
||||
String IRmessages[maxCountMessages];
|
||||
int messagePos = 0;
|
||||
int messageCount = 0;
|
||||
|
||||
void printReceivedMessages(bool clearMessages = false) {
|
||||
//Serial.println("");
|
||||
int messagePosLoop;
|
||||
if (messageCount < maxCountMessages) {
|
||||
messagePosLoop = 0;
|
||||
} else {
|
||||
messagePosLoop = messagePos;
|
||||
}
|
||||
|
||||
//Serial.printf("will start printing messages, beginning at position %d\r\n", messagePosLoop);
|
||||
for (int i=0; i<maxCountMessages; i++) {
|
||||
if (clearMessages) {
|
||||
IRmessages[messagePosLoop] = "";
|
||||
}
|
||||
//Serial.printf("will print at line %d the message at position %d: %s\r\n", i, messagePosLoop, IRmessages[messagePosLoop].c_str());
|
||||
lv_label_set_text(irReceivedMessage[i], IRmessages[messagePosLoop].c_str());
|
||||
messagePosLoop += 1;
|
||||
if (messagePosLoop == maxCountMessages) {
|
||||
messagePosLoop = 0;
|
||||
}
|
||||
}
|
||||
if (clearMessages) {
|
||||
lv_obj_set_size(menuBoxMessages, lv_pct(100), boxHeightDeactivated);
|
||||
}
|
||||
}
|
||||
|
||||
void showNewIRmessage(String message) {
|
||||
resetStandbyTimer(); // Reset the sleep timer when a IR message is received
|
||||
|
||||
// Serial.printf(" new IR message received: %s\r\n", message.c_str());
|
||||
// const char *a = message.c_str();
|
||||
std::string messageStr;
|
||||
messageStr.append(message.c_str());
|
||||
// std::string aMessage = s(a);
|
||||
messageStr.erase(std::remove(messageStr.begin(), messageStr.end(), '\n'), messageStr.cend());
|
||||
|
||||
//Serial.printf(" will put message %s to list\r\n", messageStr.c_str());
|
||||
messageCount += 1;
|
||||
IRmessages[messagePos] = (std::to_string(messageCount) + ": " + messageStr).c_str();
|
||||
//Serial.printf(" this is the message at position %d: %s\r\n", messagePos, IRmessages[messagePos].c_str());
|
||||
messagePos += 1;
|
||||
if (messagePos == maxCountMessages) {
|
||||
messagePos = 0;
|
||||
}
|
||||
printReceivedMessages();
|
||||
}
|
||||
|
||||
// IR receiver on Switch Event handler
|
||||
static void IRReceiverOnSetting_event_cb(lv_event_t * e){
|
||||
irReceiverEnabled = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
|
||||
if (irReceiverEnabled) {
|
||||
Serial.println("will turn on IR receiver");
|
||||
init_infraredReceiver();
|
||||
lv_obj_set_size(menuBoxMessages, lv_pct(100), boxHeightActivated);
|
||||
messageCount = 0;
|
||||
printReceivedMessages();
|
||||
} else {
|
||||
Serial.println("will turn off IR receiver");
|
||||
shutdown_infraredReceiver();
|
||||
printReceivedMessages(true);
|
||||
messagePos = 0;
|
||||
messageCount = 0;
|
||||
lv_obj_set_size(menuBoxMessages, lv_pct(100), boxHeightDeactivated);
|
||||
}
|
||||
}
|
||||
|
||||
void init_gui_tab_irReceiver(lv_obj_t* tabview) {
|
||||
|
||||
lv_obj_t* tab = lv_tabview_add_tab(tabview, "IR Receiver");
|
||||
|
||||
// Add content to the settings tab
|
||||
// With a flex layout, setting groups/boxes will position themselves automatically
|
||||
lv_obj_set_layout(tab, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(tab, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(tab, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
menuBoxToggle = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBoxToggle, lv_pct(100), 48);
|
||||
lv_obj_set_style_bg_color(menuBoxToggle, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBoxToggle, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* menuLabel = lv_label_create(menuBoxToggle);
|
||||
lv_label_set_text(menuLabel, "Turn on IR receiver");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 3);
|
||||
lv_obj_t* irReceiverToggle = lv_switch_create(menuBoxToggle);
|
||||
lv_obj_set_size(irReceiverToggle, 40, 22);
|
||||
lv_obj_align(irReceiverToggle, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(irReceiverToggle, lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(irReceiverToggle, IRReceiverOnSetting_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
// lv_obj_add_state(irReceiverToggle, LV_STATE_CHECKED); // set default state
|
||||
|
||||
|
||||
menuBoxMessages = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBoxMessages, lv_pct(100), 77); // 125
|
||||
lv_obj_set_style_bg_color(menuBoxMessages, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBoxMessages, 0, LV_PART_MAIN);
|
||||
|
||||
for (int i=0; i<maxCountMessages; i++) {
|
||||
irReceivedMessage[i] = lv_label_create(menuBoxMessages);
|
||||
lv_obj_set_style_text_font(irReceivedMessage[i], &lv_font_montserrat_10, LV_PART_MAIN);
|
||||
lv_obj_align(irReceivedMessage[i], LV_ALIGN_TOP_LEFT, 0, 0 + i*11);
|
||||
}
|
||||
printReceivedMessages(true);
|
||||
}
|
||||
|
||||
void init_gui_pageIndicator_irReceiver(lv_obj_t* panel) {
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "IR Receiver");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
void register_gui_irReceiver(void){
|
||||
register_gui(& init_gui_tab_irReceiver, & init_gui_pageIndicator_irReceiver);
|
||||
}
|
10
Platformio/src/gui_general_and_keys/gui_irReceiver.h
Normal file
10
Platformio/src/gui_general_and_keys/gui_irReceiver.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef __GUI_IRRECEIVER_H__
|
||||
#define __GUI_IRRECEIVER_H__
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <string>
|
||||
|
||||
void register_gui_irReceiver(void);
|
||||
void showNewIRmessage(String);
|
||||
|
||||
#endif /*__GUI_IRRECEIVER_H__*/
|
101
Platformio/src/gui_general_and_keys/gui_numpad.cpp
Normal file
101
Platformio/src/gui_general_and_keys/gui_numpad.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
#include <lvgl.h>
|
||||
#include "hardware/tft.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/guiRegistry.h"
|
||||
#include "commandHandler.h"
|
||||
#include "scenes/sceneHandler.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
|
||||
// Virtual Keypad Event handler
|
||||
static void virtualKeypad_event_cb(lv_event_t* e) {
|
||||
lv_obj_t* target = lv_event_get_target(e);
|
||||
lv_obj_t* cont = lv_event_get_current_target(e);
|
||||
if (target == cont) return; // stop if container was clicked
|
||||
|
||||
// send corrensponding number
|
||||
if (currentScene == scene_name_TV) {
|
||||
std::string virtualKeyMapTVNumbers[10] = {SAMSUNG_NUM_1, SAMSUNG_NUM_2, SAMSUNG_NUM_3, SAMSUNG_NUM_4, SAMSUNG_NUM_5, SAMSUNG_NUM_6, SAMSUNG_NUM_7, SAMSUNG_NUM_8, SAMSUNG_NUM_9, SAMSUNG_NUM_0};
|
||||
std::string command = virtualKeyMapTVNumbers[(int)target->user_data];
|
||||
executeCommand(command);
|
||||
|
||||
} else if (currentScene == scene_name_fireTV) {
|
||||
byte virtualKeyMapFireTVNumbers[10] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0};
|
||||
int number = virtualKeyMapFireTVNumbers[(int)target->user_data];
|
||||
std::string numberStr = std::to_string(number);
|
||||
executeCommand(KEYBOARD_SENDSTRING, numberStr);
|
||||
}
|
||||
}
|
||||
|
||||
void init_gui_tab_numpad(lv_obj_t* tabview) {
|
||||
|
||||
lv_obj_t* tab = lv_tabview_add_tab(tabview, "Numpad");
|
||||
|
||||
// Configure number button grid
|
||||
static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution
|
||||
static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit
|
||||
|
||||
// Create a container with grid for tab
|
||||
lv_obj_set_style_pad_all(tab, 0, LV_PART_MAIN);
|
||||
lv_obj_t* cont = lv_obj_create(tab);
|
||||
lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_grid_column_dsc_array(cont, col_dsc, 0);
|
||||
lv_obj_set_style_grid_row_dsc_array(cont, row_dsc, 0);
|
||||
lv_obj_set_size(cont, 240, 270);
|
||||
lv_obj_set_layout(cont, LV_LAYOUT_GRID);
|
||||
lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_radius(cont, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* buttonLabel;
|
||||
lv_obj_t* obj;
|
||||
|
||||
// Iterate through grid buttons configure them
|
||||
for (int i = 0; i < 12; i++) {
|
||||
uint8_t col = i % 3;
|
||||
uint8_t row = i / 3;
|
||||
// Create the button object
|
||||
if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button
|
||||
obj = lv_btn_create(cont);
|
||||
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1);
|
||||
lv_obj_set_style_bg_color(obj, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(obj, 14, LV_PART_MAIN);
|
||||
lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN);
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container
|
||||
// Create Labels for each button
|
||||
buttonLabel = lv_label_create(obj);
|
||||
if(i < 9){
|
||||
lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row);
|
||||
lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event
|
||||
}
|
||||
else{
|
||||
lv_label_set_text_fmt(buttonLabel, "0", col, row);
|
||||
lv_obj_set_user_data(obj, (void*)9);
|
||||
}
|
||||
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN);
|
||||
lv_obj_center(buttonLabel);
|
||||
}
|
||||
// Create a shared event for all button inside container
|
||||
lv_obj_add_event_cb(cont, virtualKeypad_event_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void init_gui_pageIndicator_numpad(lv_obj_t* panel) {
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Numpad");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
}
|
||||
|
||||
void register_gui_numpad(void){
|
||||
register_gui(& init_gui_tab_numpad, & init_gui_pageIndicator_numpad);
|
||||
}
|
8
Platformio/src/gui_general_and_keys/gui_numpad.h
Normal file
8
Platformio/src/gui_general_and_keys/gui_numpad.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __GUI_NUMPAD_H__
|
||||
#define __GUI_NUMPAD_H__
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
void register_gui_numpad(void);
|
||||
|
||||
#endif /*__GUI_NUMPAD_H__*/
|
178
Platformio/src/gui_general_and_keys/gui_settings.cpp
Normal file
178
Platformio/src/gui_general_and_keys/gui_settings.cpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include <lvgl.h>
|
||||
#include "preferencesStorage.h"
|
||||
#include "hardware/tft.h"
|
||||
#include "hardware/sleep.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/guiRegistry.h"
|
||||
|
||||
lv_obj_t* objBattSettingsVoltage;
|
||||
lv_obj_t* objBattSettingsPercentage;
|
||||
//lv_obj_t* objBattSettingsIscharging;
|
||||
|
||||
// Slider Event handler
|
||||
static void bl_slider_event_cb(lv_event_t * e){
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
backlight_brightness = constrain(lv_slider_get_value(slider), 60, 255);
|
||||
}
|
||||
|
||||
// Wakeup by IMU Switch Event handler
|
||||
static void WakeEnableSetting_event_cb(lv_event_t * e){
|
||||
wakeupByIMUEnabled = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
// timout event handler
|
||||
static void timout_event_cb(lv_event_t * e){
|
||||
lv_obj_t * drop = lv_event_get_target(e);
|
||||
uint16_t selected = lv_dropdown_get_selected(drop);
|
||||
switch (selected) {
|
||||
case 0: {actualSleepTimeout = 10000; break;}
|
||||
case 1: {actualSleepTimeout = 20000; break;}
|
||||
case 2: {actualSleepTimeout = 40000; break;}
|
||||
case 3: {actualSleepTimeout = 60000; break;}
|
||||
case 4: {actualSleepTimeout = 180000; break;}
|
||||
case 5: {actualSleepTimeout = 600000; break;}
|
||||
case 6: {actualSleepTimeout = 3600000; break;}
|
||||
}
|
||||
// Serial.printf("New timeout: %lu ms\r\n", actualSleepTimeout);
|
||||
resetStandbyTimer();
|
||||
// save preferences now, otherwise if you set a very big timeout and upload your firmware again, it never got saved
|
||||
save_preferences();
|
||||
}
|
||||
|
||||
void init_gui_tab_settings(lv_obj_t* tabview) {
|
||||
|
||||
lv_obj_t* tab = lv_tabview_add_tab(tabview, "Settings");
|
||||
|
||||
|
||||
// Add content to the settings tab
|
||||
// With a flex layout, setting groups/boxes will position themselves automatically
|
||||
lv_obj_set_layout(tab, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(tab, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(tab, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
// Add a label, then a box for the display settings
|
||||
lv_obj_t* menuLabel = lv_label_create(tab);
|
||||
lv_label_set_text(menuLabel, "Display");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 109);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* brightnessIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(brightnessIcon, &low_brightness);
|
||||
lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_t* slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 60, 255);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, backlight_brightness, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(66), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
|
||||
brightnessIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(brightnessIcon, &high_brightness);
|
||||
lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1);
|
||||
lv_obj_add_event_cb(slider, bl_slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Lift to Wake");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
lv_obj_t* wakeToggle = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(wakeToggle, 40, 22);
|
||||
lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29);
|
||||
lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(wakeToggle, WakeEnableSetting_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(wakeupByIMUEnabled) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Timeout");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
|
||||
lv_obj_t* drop = lv_dropdown_create(menuBox);
|
||||
lv_dropdown_set_options(drop, "10s\n"
|
||||
"20s\n"
|
||||
"40s\n"
|
||||
"1m\n"
|
||||
"3m\n"
|
||||
"10m\n"
|
||||
"1h"); // 1h for debug purposes, if you don't want the device to go to slepp
|
||||
// if you add more options here, do the same in timout_event_cb()
|
||||
switch (actualSleepTimeout) {
|
||||
case 10000: {lv_dropdown_set_selected(drop, 0); break;}
|
||||
case 20000: {lv_dropdown_set_selected(drop, 1); break;}
|
||||
case 40000: {lv_dropdown_set_selected(drop, 2); break;}
|
||||
case 60000: {lv_dropdown_set_selected(drop, 3); break;}
|
||||
case 180000: {lv_dropdown_set_selected(drop, 4); break;}
|
||||
case 600000: {lv_dropdown_set_selected(drop, 5); break;}
|
||||
case 3600000: {lv_dropdown_set_selected(drop, 6); break;}
|
||||
}
|
||||
lv_dropdown_set_selected_highlight(drop, true);
|
||||
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
|
||||
lv_obj_set_size(drop, 70, 22);
|
||||
//lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
//lv_obj_set_style_text_font(lv_dropdown_get_list(drop), &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(drop, timout_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
// // Add another label, then a settings box for WiFi
|
||||
// menuLabel = lv_label_create(tab);
|
||||
// lv_label_set_text(menuLabel, "Wi-Fi");
|
||||
// menuBox = lv_obj_create(tab);
|
||||
// lv_obj_set_size(menuBox, lv_pct(100), 80);
|
||||
// lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
// lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
// menuLabel = lv_label_create(menuBox);
|
||||
// lv_label_set_text(menuLabel, "Network");
|
||||
// menuLabel = lv_label_create(menuBox);
|
||||
// lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT);
|
||||
// lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
// menuLabel = lv_label_create(menuBox);
|
||||
// lv_label_set_text(menuLabel, "Password");
|
||||
// lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
// menuLabel = lv_label_create(menuBox);
|
||||
// lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT);
|
||||
// lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 32);
|
||||
|
||||
// Another setting for the battery
|
||||
menuLabel = lv_label_create(tab);
|
||||
lv_label_set_text(menuLabel, "Battery");
|
||||
menuBox = lv_obj_create(tab);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 77); // 125
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
objBattSettingsVoltage = lv_label_create(menuBox);
|
||||
lv_label_set_text(objBattSettingsVoltage, "Voltage:");
|
||||
lv_obj_align(objBattSettingsVoltage, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
objBattSettingsPercentage = lv_label_create(menuBox);
|
||||
lv_label_set_text(objBattSettingsPercentage, "Percentage:");
|
||||
lv_obj_align(objBattSettingsPercentage, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
// objBattSettingsIscharging = lv_label_create(menuBox);
|
||||
// lv_label_set_text(objBattSettingsIscharging, "Is charging:");
|
||||
// lv_obj_align(objBattSettingsIscharging, LV_ALIGN_TOP_LEFT, 0, 64);
|
||||
}
|
||||
|
||||
void init_gui_pageIndicator_settings(lv_obj_t* panel) {
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Settings");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
}
|
||||
|
||||
void register_gui_settings(void){
|
||||
register_gui(& init_gui_tab_settings, & init_gui_pageIndicator_settings);
|
||||
}
|
12
Platformio/src/gui_general_and_keys/gui_settings.h
Normal file
12
Platformio/src/gui_general_and_keys/gui_settings.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __GUI_SETTINGS_H__
|
||||
#define __GUI_SETTINGS_H__
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
extern lv_obj_t* objBattSettingsVoltage;
|
||||
extern lv_obj_t* objBattSettingsPercentage;
|
||||
//extern lv_obj_t* objBattSettingsIscharging;
|
||||
|
||||
void register_gui_settings(void);
|
||||
|
||||
#endif /*__GUI_SETTINGS_H__*/
|
176
Platformio/src/gui_general_and_keys/keys.cpp
Normal file
176
Platformio/src/gui_general_and_keys/keys.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
#include <map>
|
||||
#include <string.h>
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
#include "hardware/sleep.h"
|
||||
#include "hardware/infrared_sender.h"
|
||||
#include "hardware/mqtt.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/sceneHandler.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
const byte ROWS = 5; //five rows
|
||||
const byte COLS = 5; //five columns
|
||||
|
||||
// Keypad declarations
|
||||
// define the symbols on the buttons of the keypads
|
||||
char hexaKeys[ROWS][COLS] = {
|
||||
{'s','^','-','m','e'}, // source, channel+, Volume-, mute, record
|
||||
{'i','r','+','k','d'}, // info, right, Volume+, OK, down
|
||||
{'4','v','1','3','2'}, // blue, channel-, red, yellow, green
|
||||
{'>','o','b','u','l'}, // forward, off, back, up, left
|
||||
{'?','p','c','<','='} // ?, play, config, rewind, stop
|
||||
};
|
||||
/*
|
||||
off o
|
||||
|
||||
stop = rewind < play p forward >
|
||||
|
||||
config c info i
|
||||
up u
|
||||
left l OK k right r
|
||||
down d
|
||||
back b source s
|
||||
|
||||
Volume+ + mute m channel+ ^
|
||||
Volume- - record e channel- v
|
||||
|
||||
red 1 green 2 yellow 3 blue 4
|
||||
*/
|
||||
byte rowPins[ROWS] = {SW_A, SW_B, SW_C, SW_D, SW_E}; //connect to the row pinouts of the keypad
|
||||
byte colPins[COLS] = {SW_1, SW_2, SW_3, SW_4, SW_5}; //connect to the column pinouts of the keypad
|
||||
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
|
||||
|
||||
void init_keys(void) {
|
||||
// Button Pin Definition
|
||||
pinMode(SW_1, OUTPUT);
|
||||
pinMode(SW_2, OUTPUT);
|
||||
pinMode(SW_3, OUTPUT);
|
||||
pinMode(SW_4, OUTPUT);
|
||||
pinMode(SW_5, OUTPUT);
|
||||
pinMode(SW_A, INPUT);
|
||||
pinMode(SW_B, INPUT);
|
||||
pinMode(SW_C, INPUT);
|
||||
pinMode(SW_D, INPUT);
|
||||
pinMode(SW_E, INPUT);
|
||||
}
|
||||
|
||||
KeyState lastKeyState[ROWS][COLS] = {
|
||||
{IDLE,IDLE,IDLE,IDLE,IDLE},
|
||||
{IDLE,IDLE,IDLE,IDLE,IDLE},
|
||||
{IDLE,IDLE,IDLE,IDLE,IDLE},
|
||||
{IDLE,IDLE,IDLE,IDLE,IDLE},
|
||||
{IDLE,IDLE,IDLE,IDLE,IDLE},
|
||||
};
|
||||
unsigned long lastTimeSent[ROWS][COLS] ={
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
};
|
||||
bool keyIsHold[ROWS][COLS] = {
|
||||
{false,false,false,false,false},
|
||||
{false,false,false,false,false},
|
||||
{false,false,false,false,false},
|
||||
{false,false,false,false,false},
|
||||
{false,false,false,false,false}
|
||||
};
|
||||
int repeatRate = 125; // in milliseconds
|
||||
|
||||
void doShortPress(char keyChar, int keyCode){
|
||||
unsigned long currentMillis = millis();
|
||||
if ((currentMillis - lastTimeSent[keyCode/ROWS][keyCode%ROWS]) > repeatRate) {
|
||||
lastTimeSent[keyCode/ROWS][keyCode%ROWS] = currentMillis;
|
||||
|
||||
std::string command = get_command_short(currentScene, keyChar);
|
||||
if (command != COMMAND_UNKNOWN) {
|
||||
Serial.printf("key: key '%c', will use command '%s'\r\n", keyChar, command.c_str());
|
||||
executeCommand(command);
|
||||
} else {
|
||||
Serial.printf("key: key '%c', but no command defined\r\n", keyChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doLongPress(char keyChar, int keyCode){
|
||||
std::string command = get_command_long(currentScene, keyChar);
|
||||
if (command != COMMAND_UNKNOWN) {
|
||||
Serial.printf("key: key '%c' (long press), will use command '%s'\r\n", keyChar, command.c_str());
|
||||
executeCommand(command);
|
||||
} else {
|
||||
Serial.printf("key: key '%c' (long press), but no command defined\r\n", keyChar);
|
||||
}
|
||||
}
|
||||
|
||||
void keypad_loop(void) {
|
||||
// we have to ignore the result, because in case of SINGLE_REPEATED we want to send the command again and again, but the keypad would give us only one single HOLD state, not repeatedly
|
||||
customKeypad.getKeys();
|
||||
|
||||
for(int i=0; i < LIST_MAX; i++) {
|
||||
if (!customKeypad.key[i].stateChanged) {
|
||||
// we are not allowed to do this, because of the same reason as above
|
||||
// continue;
|
||||
} else {
|
||||
resetStandbyTimer(); // Reset the sleep timer when a button is pressed
|
||||
}
|
||||
char keyChar = customKeypad.key[i].kchar;
|
||||
int keyCode = customKeypad.key[i].kcode;
|
||||
|
||||
if (customKeypad.key[i].kstate == PRESSED) {
|
||||
// Serial.println("pressed");
|
||||
|
||||
if ((get_key_repeatMode(currentScene, keyChar) == SHORT) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != PRESSED)) {
|
||||
// Serial.printf("key: PRESSED of SHORT key %c (%d)\r\n", keyChar, keyCode);
|
||||
doShortPress(keyChar, keyCode);
|
||||
|
||||
} else if ((get_key_repeatMode(currentScene, keyChar) == SHORT_REPEATED) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != PRESSED)) { // here do not repeat it too early, do the repeat only in HOLD
|
||||
// Serial.printf("key: PRESSED of SHORT_REPEATED key %c (%d)\r\n", keyChar, keyCode);
|
||||
doShortPress(keyChar, keyCode);
|
||||
|
||||
}
|
||||
lastKeyState[keyCode/ROWS][keyCode%ROWS] = PRESSED;
|
||||
|
||||
} else if (customKeypad.key[i].kstate == HOLD) {
|
||||
// Serial.println("hold");
|
||||
|
||||
if ((get_key_repeatMode(currentScene, keyChar) == SHORTorLONG) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != HOLD)) {
|
||||
// Serial.printf("key: HOLD of SHORTorLONG key %c (%d)\r\n", keyChar, keyCode);
|
||||
// Serial.printf("will set keyIsHold to TRUE for keycode %d\r\n", keyCode);
|
||||
keyIsHold[keyCode/ROWS][keyCode%ROWS] = true;
|
||||
doLongPress(keyChar, keyCode);
|
||||
|
||||
} else if (get_key_repeatMode(currentScene, keyChar) == SHORT_REPEATED) { // this is the only case where we do not check the lastKeyState, because here it is intended to repeat the action
|
||||
// Serial.printf("key: HOLD of SHORT_REPEATED key %c (%d)\r\n", keyChar, keyCode);
|
||||
doShortPress(keyChar, keyCode);
|
||||
|
||||
}
|
||||
lastKeyState[keyCode/ROWS][keyCode%ROWS] = HOLD;
|
||||
|
||||
} else if (customKeypad.key[i].kstate == RELEASED) {
|
||||
// Serial.println("released");
|
||||
if ((get_key_repeatMode(currentScene, keyChar) == SHORTorLONG) && !keyIsHold[keyCode/ROWS][keyCode%ROWS] && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != RELEASED)) {
|
||||
// Serial.printf("value of keyIsHold for keycode %d is %d\r\n", keyCode, keyIsHold[keyCode/ROWS][keyCode%ROWS]);
|
||||
// Serial.printf("key: RELEASED of SHORTorLONG key %c (%d)\r\n", keyChar, keyCode);
|
||||
doShortPress(keyChar, keyCode);
|
||||
}
|
||||
// Serial.printf("will set keyIsHold to FALSE for keycode %d\r\n", keyCode);
|
||||
keyIsHold[keyCode/ROWS][keyCode%ROWS] = false;
|
||||
|
||||
// Serial.printf("key: press of key %c (%d)\r\n", keyChar, keyCode);
|
||||
lastKeyState[keyCode/ROWS][keyCode%ROWS] = RELEASED;
|
||||
|
||||
} else if (customKeypad.key[i].kstate == IDLE) {
|
||||
// Serial.println("idle");
|
||||
|
||||
// Serial.printf("key: idle of key %c (%d)\r\n", keyChar, keyCode);
|
||||
lastKeyState[keyCode/ROWS][keyCode%ROWS] = IDLE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
37
Platformio/src/gui_general_and_keys/keys.h
Normal file
37
Platformio/src/gui_general_and_keys/keys.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef __KEYS_H__
|
||||
#define __KEYS_H__
|
||||
|
||||
#include <Keypad.h> // modified for inverted logic
|
||||
|
||||
#define SW_1 32 // 1...5: Output
|
||||
#define SW_2 26
|
||||
#define SW_3 27
|
||||
#define SW_4 14
|
||||
#define SW_5 12
|
||||
#define SW_A 37 // A...E: Input
|
||||
#define SW_B 38
|
||||
#define SW_C 39
|
||||
#define SW_D 34
|
||||
#define SW_E 35
|
||||
|
||||
#define BUTTON_PIN_BITMASK 0b1110110000000000000000000010000000000000 //IO34+IO35+IO37+IO38+IO39(+IO13)
|
||||
|
||||
enum repeatModes {
|
||||
// only as fallback
|
||||
REPEAT_MODE_UNKNOWN,
|
||||
// if you short press or hold a key on the keypad, only one single command from keyCommands_short is sent
|
||||
// -> best used if you do not want a command to be sent more than once, even if you press the key (too) long, e.g. when toggling power
|
||||
SHORT,
|
||||
// if you hold a key on the keypad, a command from keyCommands_short is sent repeatedly
|
||||
// -> best used e.g. for holding the key for "volume up"
|
||||
SHORT_REPEATED,
|
||||
// if you short press a key, a command from keyCommands_short is sent once.
|
||||
// if you hold a key on the keypad, a command from keyCommands_long is sent (no command from keyCommands_short before)
|
||||
// -> best used if a long key press should send a different command than a short press
|
||||
SHORTorLONG,
|
||||
};
|
||||
|
||||
void init_keys(void);
|
||||
void keypad_loop(void);
|
||||
|
||||
#endif /*__KEYS_H__*/
|
|
@ -49,7 +49,7 @@
|
|||
#define LV_MEM_CUSTOM 0
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
|
||||
#define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/
|
||||
#define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/
|
||||
|
||||
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||
#define LV_MEM_ADR 0 /*0: unused*/
|
||||
|
@ -354,7 +354,7 @@
|
|||
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||
*https://fonts.google.com/specimen/Montserrat*/
|
||||
#define LV_FONT_MONTSERRAT_8 0
|
||||
#define LV_FONT_MONTSERRAT_10 0
|
||||
#define LV_FONT_MONTSERRAT_10 1
|
||||
#define LV_FONT_MONTSERRAT_12 1
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 1
|
75
Platformio/src/hardware/battery.cpp
Normal file
75
Platformio/src/hardware/battery.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include <Arduino.h>
|
||||
#include "hardware/battery.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/gui_settings.h"
|
||||
|
||||
void init_battery(void) {
|
||||
// Currently the battery charge status cannot be recognized in a reliable way due to a design flaw in the PCB.
|
||||
// See https://github.com/CoretechR/OMOTE/issues/55
|
||||
// So charge status is deactivated for now.
|
||||
//pinMode(CRG_STAT, INPUT_PULLUP);
|
||||
pinMode(ADC_BAT, INPUT);
|
||||
}
|
||||
|
||||
// Battery declares
|
||||
int battery_analogRead = 0;
|
||||
int battery_voltage = 0;
|
||||
int battery_percentage = 100;
|
||||
//bool battery_ischarging = false;
|
||||
|
||||
void update_battery_stats(void) {
|
||||
battery_analogRead = analogRead(ADC_BAT);
|
||||
// original values
|
||||
// battery_voltage = battery_analogRead*2*3300/4095 + 350; // 350mV ADC offset
|
||||
// adjusted values due to new measurements
|
||||
battery_voltage = battery_analogRead*2*3350/4095 + 325;
|
||||
battery_percentage = constrain(map(battery_voltage, 3700, 4200, 0, 100), 0, 100);
|
||||
// Check if battery is charging, fully charged or disconnected
|
||||
/*
|
||||
"disconnected" cannot be recognized
|
||||
https://electronics.stackexchange.com/questions/615215/level-shifting-of-a-3-state-pin
|
||||
https://electrical.codidact.com/posts/286209
|
||||
https://how2electronics.com/lithium-ion-battery-charger-circuit-using-mcp73831/
|
||||
*/
|
||||
//battery_ischarging = !digitalRead(CRG_STAT);
|
||||
|
||||
char buffer1[20];
|
||||
sprintf(buffer1, "Voltage: %.2f V", (float)battery_voltage / 1000);
|
||||
|
||||
// GUI settings
|
||||
lv_label_set_text_fmt(objBattSettingsVoltage, buffer1);
|
||||
lv_label_set_text_fmt(objBattSettingsPercentage, "Percentage: %d%%", battery_percentage);
|
||||
//lv_label_set_text_fmt(objBattSettingsIscharging, "Is charging: %s", battery_ischarging ? "yes" : "no");
|
||||
|
||||
// GUI status bar at the top
|
||||
char buffer2[12];
|
||||
// Voltage and percentage
|
||||
// sprintf(buffer2, "%.1fV, %d%%", (float)battery_voltage / 1000, battery_percentage);
|
||||
// only percentage
|
||||
sprintf(buffer2, "%d%%", battery_percentage);
|
||||
// sprintf(buffer, "%d%%", battery_percentage);
|
||||
for (int i=0; i<strlen(buffer2); i++) {
|
||||
if (buffer2[i] == '.') {
|
||||
buffer2[i] = ',';
|
||||
}
|
||||
}
|
||||
|
||||
// if (battery_ischarging /*|| (!battery_ischarging && battery_voltage > 4350)*/){
|
||||
// // lv_label_set_text(objBattPercentage, "");
|
||||
// // lv_label_set_text_fmt(objBattPercentage, "%d%%", battery_percentage);
|
||||
// // lv_label_set_text_fmt(objBattPercentage, "%.1f, %d%%", (float)battery_voltage / 1000, battery_percentage);
|
||||
// lv_label_set_text(objBattPercentage, buffer2);
|
||||
// lv_label_set_text(objBattIcon, LV_SYMBOL_USB);
|
||||
// } else
|
||||
{
|
||||
// Update status bar battery indicator
|
||||
// lv_label_set_text_fmt(objBattPercentage, "%.1f, %d%%", (float)battery_voltage / 1000, battery_percentage);
|
||||
lv_label_set_text(objBattPercentage, buffer2);
|
||||
if(battery_percentage > 95) lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_FULL);
|
||||
else if(battery_percentage > 75) lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_3);
|
||||
else if(battery_percentage > 50) lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_2);
|
||||
else if(battery_percentage > 25) lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_1);
|
||||
else lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
}
|
||||
}
|
||||
|
12
Platformio/src/hardware/battery.h
Normal file
12
Platformio/src/hardware/battery.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __BATTERY_H__
|
||||
#define __BATTERY_H__
|
||||
|
||||
//#define CRG_STAT 21 // battery charger feedback, GPIO21, VSPIHD, EMAC_TX_EN
|
||||
#define ADC_BAT 36 // Battery voltage sense input (1/2 divider), GPIO36, ADC1_CH0, RTC_GPIO0
|
||||
|
||||
extern int battery_percentage;
|
||||
|
||||
void init_battery(void);
|
||||
void update_battery_stats(void);
|
||||
|
||||
#endif /*__BATTERY_H__*/
|
197
Platformio/src/hardware/infrared_receiver.cpp
Normal file
197
Platformio/src/hardware/infrared_receiver.cpp
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
Mainly based on IRrecvDumpV2 from IRremoteESP8266
|
||||
Slightly changed to run with OMOTE hardware.
|
||||
*/
|
||||
|
||||
/*
|
||||
* IRremoteESP8266: IRrecvDumpV2 - dump details of IR codes with IRrecv
|
||||
* An IR detector/demodulator must be connected to the input kRecvPin.
|
||||
*
|
||||
* Copyright 2009 Ken Shirriff, http://arcfn.com
|
||||
* Copyright 2017-2019 David Conran
|
||||
*
|
||||
* Example circuit diagram:
|
||||
* https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-receiving
|
||||
*
|
||||
* Changes:
|
||||
* Version 1.2 October, 2020
|
||||
* - Enable easy setting of the decoding tolerance value.
|
||||
* Version 1.0 October, 2019
|
||||
* - Internationalisation (i18n) support.
|
||||
* - Stop displaying the legacy raw timing info.
|
||||
* Version 0.5 June, 2019
|
||||
* - Move A/C description to IRac.cpp.
|
||||
* Version 0.4 July, 2018
|
||||
* - Minor improvements and more A/C unit support.
|
||||
* Version 0.3 November, 2017
|
||||
* - Support for A/C decoding for some protocols.
|
||||
* Version 0.2 April, 2017
|
||||
* - Decode from a copy of the data so we can start capturing faster thus
|
||||
* reduce the likelihood of miscaptures.
|
||||
* Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009,
|
||||
*/
|
||||
|
||||
//#include <Arduino.h>
|
||||
#include <assert.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRac.h>
|
||||
#include <IRtext.h>
|
||||
#include <IRutils.h>
|
||||
|
||||
#include "hardware/infrared_receiver.h"
|
||||
#include "gui_general_and_keys/gui_irReceiver.h"
|
||||
|
||||
bool irReceiverEnabled = false;
|
||||
|
||||
// The Serial connection baud rate.
|
||||
// i.e. Status message will be sent to the PC at this baud rate.
|
||||
// Try to avoid slow speeds like 9600, as you will miss messages and
|
||||
// cause other problems. 115200 (or faster) is recommended.
|
||||
// NOTE: Make sure you set your Serial Monitor to the same speed.
|
||||
const uint32_t kBaudRate = 115200;
|
||||
|
||||
// As this program is a special purpose capture/decoder, let us use a larger
|
||||
// than normal buffer so we can handle Air Conditioner remote codes.
|
||||
const uint16_t kCaptureBufferSize = 1024;
|
||||
|
||||
// kTimeout is the Nr. of milli-Seconds of no-more-data before we consider a
|
||||
// message ended.
|
||||
// This parameter is an interesting trade-off. The longer the timeout, the more
|
||||
// complex a message it can capture. e.g. Some device protocols will send
|
||||
// multiple message packets in quick succession, like Air Conditioner remotes.
|
||||
// Air Coniditioner protocols often have a considerable gap (20-40+ms) between
|
||||
// packets.
|
||||
// The downside of a large timeout value is a lot of less complex protocols
|
||||
// send multiple messages when the remote's button is held down. The gap between
|
||||
// them is often also around 20+ms. This can result in the raw data be 2-3+
|
||||
// times larger than needed as it has captured 2-3+ messages in a single
|
||||
// capture. Setting a low timeout value can resolve this.
|
||||
// So, choosing the best kTimeout value for your use particular case is
|
||||
// quite nuanced. Good luck and happy hunting.
|
||||
// NOTE: Don't exceed kMaxTimeoutMs. Typically 130ms.
|
||||
#if DECODE_AC
|
||||
// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator
|
||||
// A value this large may swallow repeats of some protocols
|
||||
const uint8_t kTimeout = 50;
|
||||
#else // DECODE_AC
|
||||
// Suits most messages, while not swallowing many repeats.
|
||||
const uint8_t kTimeout = 15;
|
||||
#endif // DECODE_AC
|
||||
// Alternatives:
|
||||
// const uint8_t kTimeout = 90;
|
||||
// Suits messages with big gaps like XMP-1 & some aircon units, but can
|
||||
// accidentally swallow repeated messages in the rawData[] output.
|
||||
//
|
||||
// const uint8_t kTimeout = kMaxTimeoutMs;
|
||||
// This will set it to our currently allowed maximum.
|
||||
// Values this high are problematic because it is roughly the typical boundary
|
||||
// where most messages repeat.
|
||||
// e.g. It will stop decoding a message and start sending it to serial at
|
||||
// precisely the time when the next message is likely to be transmitted,
|
||||
// and may miss it.
|
||||
|
||||
// Set the smallest sized "UNKNOWN" message packets we actually care about.
|
||||
// This value helps reduce the false-positive detection rate of IR background
|
||||
// noise as real messages. The chances of background IR noise getting detected
|
||||
// as a message increases with the length of the kTimeout value. (See above)
|
||||
// The downside of setting this message too large is you can miss some valid
|
||||
// short messages for protocols that this library doesn't yet decode.
|
||||
//
|
||||
// Set higher if you get lots of random short UNKNOWN messages when nothing
|
||||
// should be sending a message.
|
||||
// Set lower if you are sure your setup is working, but it doesn't see messages
|
||||
// from your device. (e.g. Other IR remotes work.)
|
||||
// NOTE: Set this value very high to effectively turn off UNKNOWN detection.
|
||||
const uint16_t kMinUnknownSize = 12;
|
||||
|
||||
// How much percentage lee way do we give to incoming signals in order to match
|
||||
// it?
|
||||
// e.g. +/- 25% (default) to an expected value of 500 would mean matching a
|
||||
// value between 375 & 625 inclusive.
|
||||
// Note: Default is 25(%). Going to a value >= 50(%) will cause some protocols
|
||||
// to no longer match correctly. In normal situations you probably do not
|
||||
// need to adjust this value. Typically that's when the library detects
|
||||
// your remote's message some of the time, but not all of the time.
|
||||
const uint8_t kTolerancePercentage = kTolerance; // kTolerance is normally 25%
|
||||
|
||||
// Legacy (No longer supported!)
|
||||
//
|
||||
// Change to `true` if you miss/need the old "Raw Timing[]" display.
|
||||
#define LEGACY_TIMING_INFO false
|
||||
// ==================== end of TUNEABLE PARAMETERS ====================
|
||||
|
||||
// Use turn on the save buffer feature for more complete capture coverage.
|
||||
IRrecv irrecv(IR_RX, kCaptureBufferSize, kTimeout, true);
|
||||
decode_results results; // Somewhere to store the results
|
||||
|
||||
// This section of code runs only once at start-up.
|
||||
void init_infraredReceiver() {
|
||||
pinMode(IR_RX, INPUT);
|
||||
pinMode(IR_VCC, OUTPUT);
|
||||
digitalWrite(IR_VCC, HIGH); // Turn on IR receiver
|
||||
|
||||
// Perform a low level sanity checks that the compiler performs bit field
|
||||
// packing as we expect and Endianness is as we expect.
|
||||
assert(irutils::lowLevelSanityCheck() == 0);
|
||||
|
||||
Serial.printf("\n" D_STR_IRRECVDUMP_STARTUP "\n", IR_RX);
|
||||
#if DECODE_HASH
|
||||
// Ignore messages with less than minimum on or off pulses.
|
||||
irrecv.setUnknownThreshold(kMinUnknownSize);
|
||||
#endif // DECODE_HASH
|
||||
irrecv.setTolerance(kTolerancePercentage); // Override the default tolerance.
|
||||
irrecv.enableIRIn(); // Start the receiver
|
||||
}
|
||||
|
||||
void shutdown_infraredReceiver() {
|
||||
irrecv.disableIRIn();
|
||||
digitalWrite(IR_VCC, LOW); // IR Receiver off
|
||||
}
|
||||
|
||||
// The repeating section of the code
|
||||
void infraredReceiver_loop() {
|
||||
// Check if the IR code has been received.
|
||||
if (irrecv.decode(&results)) {
|
||||
// Display a crude timestamp.
|
||||
uint32_t now = millis();
|
||||
Serial.printf(D_STR_TIMESTAMP " : %06u.%03u\n", now / 1000, now % 1000);
|
||||
// Check if we got an IR message that was to big for our capture buffer.
|
||||
if (results.overflow)
|
||||
Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize);
|
||||
// Display the library version the message was captured with.
|
||||
Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_STR "\n");
|
||||
// Display the tolerance percentage if it has been change from the default.
|
||||
if (kTolerancePercentage != kTolerance)
|
||||
Serial.printf(D_STR_TOLERANCE " : %d%%\n", kTolerancePercentage);
|
||||
// Display the basic output of what we found.
|
||||
Serial.print(resultToHumanReadableBasic(&results));
|
||||
// Display any extra A/C info if we have it.
|
||||
String description = IRAcUtils::resultAcToString(&results);
|
||||
if (description.length()) Serial.println(D_STR_MESGDESC ": " + description);
|
||||
yield(); // Feed the WDT as the text output can take a while to print.
|
||||
#if LEGACY_TIMING_INFO
|
||||
// Output legacy RAW timing info of the result.
|
||||
Serial.println(resultToTimingInfo(&results));
|
||||
yield(); // Feed the WDT (again)
|
||||
#endif // LEGACY_TIMING_INFO
|
||||
// Output the results as source code
|
||||
Serial.println(resultToSourceCode(&results));
|
||||
Serial.println(); // Blank line between entries
|
||||
|
||||
String message = "";
|
||||
message += typeToString((&results)->decode_type, (&results)->repeat);
|
||||
message += " ";
|
||||
message += resultToHexidecimal(&results);
|
||||
showNewIRmessage(message);
|
||||
|
||||
yield(); // Feed the WDT (again)
|
||||
|
||||
// if message repeats infinitely, you can try one of these two workarounds. Don't know why this is needed.
|
||||
// irrecv.resume();
|
||||
// another workaround could be:
|
||||
// irrecv.disableIRIn();
|
||||
// irrecv.enableIRIn();
|
||||
|
||||
}
|
||||
}
|
13
Platformio/src/hardware/infrared_receiver.h
Normal file
13
Platformio/src/hardware/infrared_receiver.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef __INFRARED_RECEIVER_H__
|
||||
#define __INFRARED_RECEIVER_H__
|
||||
|
||||
#define IR_RX 15 // IR receiver input
|
||||
#define IR_VCC 25 // IR receiver power
|
||||
|
||||
extern bool irReceiverEnabled;
|
||||
|
||||
void init_infraredReceiver(void);
|
||||
void shutdown_infraredReceiver(void);
|
||||
void infraredReceiver_loop(void);
|
||||
|
||||
#endif /*__INFRARED_RECEIVER_H__*/
|
15
Platformio/src/hardware/infrared_sender.cpp
Normal file
15
Platformio/src/hardware/infrared_sender.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <IRremoteESP8266.h>
|
||||
#include <IRsend.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRutils.h>
|
||||
#include "hardware/infrared_sender.h"
|
||||
|
||||
IRsend IrSender(IR_LED, true);
|
||||
|
||||
void init_infraredSender(void) {
|
||||
// IR Pin Definition
|
||||
pinMode(IR_LED, OUTPUT);
|
||||
digitalWrite(IR_LED, HIGH); // HIGH off - LOW on
|
||||
|
||||
IrSender.begin();
|
||||
}
|
14
Platformio/src/hardware/infrared_sender.h
Normal file
14
Platformio/src/hardware/infrared_sender.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef __INFRARED_H__
|
||||
#define __INFRARED_H__
|
||||
|
||||
#include <IRsend.h>
|
||||
#include <IRrecv.h>
|
||||
|
||||
#define IR_LED 33 // IR LED output
|
||||
|
||||
// IR declarations
|
||||
extern IRsend IrSender;
|
||||
|
||||
void init_infraredSender(void);
|
||||
|
||||
#endif /*__INFRARED_H__*/
|
88
Platformio/src/hardware/mqtt.cpp
Normal file
88
Platformio/src/hardware/mqtt.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include <PubSubClient.h>
|
||||
#include <lvgl.h>
|
||||
#include "hardware/mqtt.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "secrets.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
WiFiClient espClient;
|
||||
PubSubClient mqttClient(espClient);
|
||||
|
||||
// WiFi status event
|
||||
void WiFiEvent(WiFiEvent_t event){
|
||||
//Serial.printf("[WiFi-event] event: %d\r\n", event);
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP){
|
||||
// connection to MQTT server will be done in checkMQTTconnection()
|
||||
// mqttClient.setServer(MQTT_SERVER, 1883); // MQTT initialization
|
||||
// mqttClient.connect("OMOTE"); // Connect using a client id
|
||||
|
||||
}
|
||||
|
||||
// Set status bar icon based on WiFi status
|
||||
if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP || event == ARDUINO_EVENT_WIFI_STA_GOT_IP6) {
|
||||
if (WifiLabel != NULL) {lv_label_set_text(WifiLabel, LV_SYMBOL_WIFI);}
|
||||
|
||||
} else if (event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) {
|
||||
if (WifiLabel != NULL) {lv_label_set_text(WifiLabel, "");}
|
||||
// automatically try to reconnect
|
||||
Serial.printf("WiFi got disconnected. Will try to reconnect.\r\n");
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
|
||||
} else {
|
||||
// e.g. ARDUINO_EVENT_WIFI_STA_CONNECTED or many others
|
||||
// connected is not enough, will wait for IP
|
||||
if (WifiLabel != NULL) {lv_label_set_text(WifiLabel, "");}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void init_mqtt(void) {
|
||||
// Setup WiFi
|
||||
WiFi.setHostname("OMOTE"); //define hostname
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
WiFi.setSleep(true);
|
||||
}
|
||||
|
||||
bool checkMQTTconnection() {
|
||||
|
||||
if (WiFi.isConnected()) {
|
||||
if (mqttClient.connected()) {
|
||||
return true;
|
||||
} else {
|
||||
// try to connect to mqtt server
|
||||
mqttClient.setServer(MQTT_SERVER, MQTT_SERVER_PORT); // MQTT initialization
|
||||
if (mqttClient.connect(MQTT_CLIENTNAME, MQTT_USER, MQTT_PASS)) {
|
||||
Serial.printf(" Successfully connected to MQTT broker\r\n");
|
||||
|
||||
} else {
|
||||
Serial.printf(" MQTT connection failed (but WiFi is available). Will try later ...\r\n");
|
||||
|
||||
}
|
||||
return mqttClient.connected();
|
||||
}
|
||||
} else {
|
||||
Serial.printf(" No connection to MQTT server, because WiFi ist not connected.\r\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool publishMQTTMessage(const char *topic, const char *payload){
|
||||
|
||||
if (checkMQTTconnection()) {
|
||||
// Serial.printf("Sending mqtt payload to topic \"%s\": %s\r\n", topic, payload);
|
||||
|
||||
if (mqttClient.publish(topic, payload)) {
|
||||
// Serial.printf("Publish ok\r\n");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Serial.printf("Publish failed\r\n");
|
||||
}
|
||||
} else {
|
||||
Serial.printf(" Cannot publish mqtt message, because checkMQTTconnection failed (WiFi or mqtt is not connected)\r\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
15
Platformio/src/hardware/mqtt.h
Normal file
15
Platformio/src/hardware/mqtt.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef __MQTT_H__
|
||||
#define __MQTT_H__
|
||||
|
||||
#include "commandHandler.h"
|
||||
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
|
||||
#include "WiFi.h"
|
||||
#include <PubSubClient.h>
|
||||
|
||||
void init_mqtt(void);
|
||||
bool publishMQTTMessage(const char *topic, const char *payload);
|
||||
#endif
|
||||
|
||||
#endif /*__MQTT_H__*/
|
210
Platformio/src/hardware/sleep.cpp
Normal file
210
Platformio/src/hardware/sleep.cpp
Normal file
|
@ -0,0 +1,210 @@
|
|||
#include <Arduino.h>
|
||||
#include "SparkFunLIS3DH.h"
|
||||
#include "hardware/sleep.h"
|
||||
#include "hardware/tft.h"
|
||||
#include "hardware/mqtt.h"
|
||||
#include "hardware/infrared_sender.h"
|
||||
#include "hardware/infrared_receiver.h"
|
||||
#include "hardware/battery.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
#include "preferencesStorage.h"
|
||||
#include "commandHandler.h"
|
||||
#include "scenes/sceneHandler.h"
|
||||
|
||||
int motion = 0;
|
||||
uint32_t actualSleepTimeout;
|
||||
uint32_t standbyTimer;
|
||||
bool wakeupByIMUEnabled = true;
|
||||
LIS3DH IMU(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19.
|
||||
byte wakeup_reason;
|
||||
|
||||
void resetStandbyTimer() {
|
||||
standbyTimer = actualSleepTimeout;
|
||||
}
|
||||
|
||||
void activityDetection(){
|
||||
static int accXold;
|
||||
static int accYold;
|
||||
static int accZold;
|
||||
int accX = IMU.readFloatAccelX()*1000;
|
||||
int accY = IMU.readFloatAccelY()*1000;
|
||||
int accZ = IMU.readFloatAccelZ()*1000;
|
||||
|
||||
// determine motion value as da/dt
|
||||
motion = (abs(accXold - accX) + abs(accYold - accY) + abs(accZold - accZ));
|
||||
// Calculate time to standby
|
||||
standbyTimer -= 100;
|
||||
if(standbyTimer < 0) standbyTimer = 0;
|
||||
// If the motion exceeds the threshold, the standbyTimer is reset
|
||||
if(motion > MOTION_THRESHOLD) resetStandbyTimer();
|
||||
|
||||
// Store the current acceleration and time
|
||||
accXold = accX;
|
||||
accYold = accY;
|
||||
accZold = accZ;
|
||||
}
|
||||
|
||||
void configIMUInterrupts()
|
||||
{
|
||||
uint8_t dataToWrite = 0;
|
||||
|
||||
//LIS3DH_INT1_CFG
|
||||
//dataToWrite |= 0x80;//AOI, 0 = OR 1 = AND
|
||||
//dataToWrite |= 0x40;//6D, 0 = interrupt source, 1 = 6 direction source
|
||||
//Set these to enable individual axes of generation source (or direction)
|
||||
// -- high and low are used generically
|
||||
dataToWrite |= 0x20;//Z high
|
||||
//dataToWrite |= 0x10;//Z low
|
||||
dataToWrite |= 0x08;//Y high
|
||||
//dataToWrite |= 0x04;//Y low
|
||||
dataToWrite |= 0x02;//X high
|
||||
//dataToWrite |= 0x01;//X low
|
||||
if(wakeupByIMUEnabled) IMU.writeRegister(LIS3DH_INT1_CFG, 0b00101010);
|
||||
else IMU.writeRegister(LIS3DH_INT1_CFG, 0b00000000);
|
||||
|
||||
//LIS3DH_INT1_THS
|
||||
dataToWrite = 0;
|
||||
//Provide 7 bit value, 0x7F always equals max range by accelRange setting
|
||||
dataToWrite |= 0x45;
|
||||
IMU.writeRegister(LIS3DH_INT1_THS, dataToWrite);
|
||||
|
||||
//LIS3DH_INT1_DURATION
|
||||
dataToWrite = 0;
|
||||
//minimum duration of the interrupt
|
||||
//LSB equals 1/(sample rate)
|
||||
dataToWrite |= 0x00; // 1 * 1/50 s = 20ms
|
||||
IMU.writeRegister(LIS3DH_INT1_DURATION, dataToWrite);
|
||||
|
||||
//LIS3DH_CTRL_REG5
|
||||
//Int1 latch interrupt and 4D on int1 (preserve fifo en)
|
||||
IMU.readRegister(&dataToWrite, LIS3DH_CTRL_REG5);
|
||||
dataToWrite &= 0xF3; //Clear bits of interest
|
||||
dataToWrite |= 0x08; //Latch interrupt (Cleared by reading int1_src)
|
||||
//dataToWrite |= 0x04; //Pipe 4D detection from 6D recognition to int1?
|
||||
IMU.writeRegister(LIS3DH_CTRL_REG5, dataToWrite);
|
||||
|
||||
//LIS3DH_CTRL_REG3
|
||||
//Choose source for pin 1
|
||||
dataToWrite = 0;
|
||||
//dataToWrite |= 0x80; //Click detect on pin 1
|
||||
dataToWrite |= 0x40; //AOI1 event (Generator 1 interrupt on pin 1)
|
||||
dataToWrite |= 0x20; //AOI2 event ()
|
||||
//dataToWrite |= 0x10; //Data ready
|
||||
//dataToWrite |= 0x04; //FIFO watermark
|
||||
//dataToWrite |= 0x02; //FIFO overrun
|
||||
IMU.writeRegister(LIS3DH_CTRL_REG3, dataToWrite);
|
||||
|
||||
}
|
||||
|
||||
// Enter Sleep Mode
|
||||
void enterSleep(){
|
||||
// Save settings to internal flash memory
|
||||
save_preferences();
|
||||
|
||||
// Configure IMU
|
||||
uint8_t intDataRead;
|
||||
IMU.readRegister(&intDataRead, LIS3DH_INT1_SRC);//clear interrupt
|
||||
configIMUInterrupts();
|
||||
IMU.readRegister(&intDataRead, LIS3DH_INT1_SRC);//really clear interrupt
|
||||
|
||||
#ifdef ENABLE_WIFI_AND_MQTT
|
||||
// Power down modem
|
||||
WiFi.disconnect();
|
||||
WiFi.mode(WIFI_OFF);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_BLE
|
||||
bleKeyboard.end();
|
||||
#endif
|
||||
|
||||
// Prepare IO states
|
||||
digitalWrite(LCD_DC, LOW); // LCD control signals off
|
||||
digitalWrite(LCD_CS, LOW);
|
||||
digitalWrite(LCD_MOSI, LOW);
|
||||
digitalWrite(LCD_SCK, LOW);
|
||||
digitalWrite(LCD_EN, HIGH); // LCD logic off
|
||||
digitalWrite(LCD_BL, HIGH); // LCD backlight off
|
||||
// pinMode(CRG_STAT, INPUT); // Disable Pull-Up
|
||||
digitalWrite(IR_VCC, LOW); // IR Receiver off
|
||||
|
||||
// Configure button matrix for ext1 interrupt
|
||||
pinMode(SW_1, OUTPUT);
|
||||
pinMode(SW_2, OUTPUT);
|
||||
pinMode(SW_3, OUTPUT);
|
||||
pinMode(SW_4, OUTPUT);
|
||||
pinMode(SW_5, OUTPUT);
|
||||
digitalWrite(SW_1, HIGH);
|
||||
digitalWrite(SW_2, HIGH);
|
||||
digitalWrite(SW_3, HIGH);
|
||||
digitalWrite(SW_4, HIGH);
|
||||
digitalWrite(SW_5, HIGH);
|
||||
gpio_hold_en((gpio_num_t)SW_1);
|
||||
gpio_hold_en((gpio_num_t)SW_2);
|
||||
gpio_hold_en((gpio_num_t)SW_3);
|
||||
gpio_hold_en((gpio_num_t)SW_4);
|
||||
gpio_hold_en((gpio_num_t)SW_5);
|
||||
// Force display pins to high impedance
|
||||
// Without this the display might not wake up from sleep
|
||||
pinMode(LCD_BL, INPUT);
|
||||
pinMode(LCD_EN, INPUT);
|
||||
gpio_hold_en((gpio_num_t)LCD_BL);
|
||||
gpio_hold_en((gpio_num_t)LCD_EN);
|
||||
gpio_deep_sleep_hold_en();
|
||||
|
||||
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||
|
||||
delay(100);
|
||||
// Sleep
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
void init_sleep() {
|
||||
if (actualSleepTimeout == 0){
|
||||
actualSleepTimeout = DEFAULT_SLEEP_TIMEOUT;
|
||||
}
|
||||
|
||||
// Find out wakeup cause
|
||||
if(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT1){
|
||||
if(log(esp_sleep_get_ext1_wakeup_status())/log(2) == 13) wakeup_reason = WAKEUP_BY_IMU;
|
||||
else wakeup_reason = WAKEUP_BY_KEYPAD;
|
||||
}
|
||||
else {
|
||||
wakeup_reason = WAKEUP_BY_RESET;
|
||||
}
|
||||
|
||||
pinMode(ACC_INT, INPUT);
|
||||
|
||||
// Release GPIO hold in case we are coming out of standby
|
||||
gpio_hold_dis((gpio_num_t)SW_1);
|
||||
gpio_hold_dis((gpio_num_t)SW_2);
|
||||
gpio_hold_dis((gpio_num_t)SW_3);
|
||||
gpio_hold_dis((gpio_num_t)SW_4);
|
||||
gpio_hold_dis((gpio_num_t)SW_5);
|
||||
gpio_hold_dis((gpio_num_t)LCD_EN);
|
||||
gpio_hold_dis((gpio_num_t)LCD_BL);
|
||||
gpio_deep_sleep_hold_dis();
|
||||
}
|
||||
|
||||
void setup_IMU(void) {
|
||||
// Setup IMU
|
||||
IMU.settings.accelSampleRate = 50; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
|
||||
IMU.settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16
|
||||
IMU.settings.adcEnabled = 0;
|
||||
IMU.settings.tempEnabled = 0;
|
||||
IMU.settings.xAccelEnabled = 1;
|
||||
IMU.settings.yAccelEnabled = 1;
|
||||
IMU.settings.zAccelEnabled = 1;
|
||||
IMU.begin();
|
||||
uint8_t intDataRead;
|
||||
IMU.readRegister(&intDataRead, LIS3DH_INT1_SRC);//clear interrupt
|
||||
}
|
||||
|
||||
void check_activity() {
|
||||
activityDetection();
|
||||
if(standbyTimer == 0){
|
||||
Serial.println("Entering Sleep Mode. Goodbye.");
|
||||
enterSleep();
|
||||
}
|
||||
}
|
||||
|
25
Platformio/src/hardware/sleep.h
Normal file
25
Platformio/src/hardware/sleep.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef __SLEEP_H__
|
||||
#define __SLEEP_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "SparkFunLIS3DH.h"
|
||||
|
||||
#define ACC_INT 20
|
||||
|
||||
// IMU declarations
|
||||
#define DEFAULT_SLEEP_TIMEOUT 20000 // time until device enters sleep mode in milliseconds
|
||||
extern uint32_t actualSleepTimeout;
|
||||
extern uint32_t standbyTimer;
|
||||
extern bool wakeupByIMUEnabled;
|
||||
#define MOTION_THRESHOLD 50 // motion above threshold keeps device awake
|
||||
|
||||
// Other declarations
|
||||
extern byte wakeup_reason;
|
||||
enum Wakeup_reasons{WAKEUP_BY_RESET, WAKEUP_BY_IMU, WAKEUP_BY_KEYPAD};
|
||||
|
||||
void init_sleep();
|
||||
void setup_IMU();
|
||||
void check_activity();
|
||||
void resetStandbyTimer();
|
||||
|
||||
#endif /*__SLEEP_H__*/
|
71
Platformio/src/hardware/tft.cpp
Normal file
71
Platformio/src/hardware/tft.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include <Arduino.h>
|
||||
#include "driver/ledc.h"
|
||||
#include "hardware/tft.h"
|
||||
#include "hardware/sleep.h"
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
Adafruit_FT6206 touch = Adafruit_FT6206();
|
||||
TS_Point touchPoint;
|
||||
TS_Point oldPoint;
|
||||
byte backlight_brightness = 255;
|
||||
|
||||
void init_tft(void) {
|
||||
|
||||
// LCD Pin Definition
|
||||
pinMode(LCD_EN, OUTPUT);
|
||||
digitalWrite(LCD_EN, HIGH);
|
||||
pinMode(LCD_BL, OUTPUT);
|
||||
digitalWrite(LCD_BL, HIGH);
|
||||
|
||||
// Configure the backlight PWM
|
||||
// Manual setup because ledcSetup() briefly turns on the backlight
|
||||
ledc_channel_config_t ledc_channel_left;
|
||||
ledc_channel_left.gpio_num = (gpio_num_t)LCD_BL;
|
||||
ledc_channel_left.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_channel_left.channel = LEDC_CHANNEL_5;
|
||||
ledc_channel_left.intr_type = LEDC_INTR_DISABLE;
|
||||
ledc_channel_left.timer_sel = LEDC_TIMER_1;
|
||||
ledc_channel_left.flags.output_invert = 1; // Can't do this with ledcSetup()
|
||||
ledc_channel_left.duty = 0;
|
||||
|
||||
ledc_timer_config_t ledc_timer;
|
||||
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_timer.duty_resolution = LEDC_TIMER_8_BIT;
|
||||
ledc_timer.timer_num = LEDC_TIMER_1;
|
||||
ledc_timer.freq_hz = 640;
|
||||
|
||||
ledc_channel_config(&ledc_channel_left);
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
// Setup TFT
|
||||
|
||||
// Slowly charge the VSW voltage to prevent a brownout
|
||||
// Workaround for hardware rev 1!
|
||||
for(int i = 0; i < 100; i++){
|
||||
digitalWrite(LCD_EN, HIGH); // LCD Logic off
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(LCD_EN, LOW); // LCD Logic on
|
||||
}
|
||||
|
||||
delay(100); // Wait for the LCD driver to power on
|
||||
tft.init();
|
||||
tft.initDMA();
|
||||
tft.setRotation(0);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setSwapBytes(true);
|
||||
|
||||
// Setup touchscreen
|
||||
Wire.begin(SDA, SCL, 400000); // Configure i2c pins and set frequency to 400kHz
|
||||
touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
||||
}
|
||||
|
||||
void update_backligthBrighness(void) {
|
||||
static int fadeInTimer = millis(); // fadeInTimer = time after setup
|
||||
if(millis() < fadeInTimer + backlight_brightness){ // Fade in the backlight brightness
|
||||
ledcWrite(5, millis()-fadeInTimer);
|
||||
}
|
||||
else { // Dim Backlight before entering standby
|
||||
if(standbyTimer < 2000) ledcWrite(5, 85); // Backlight dim
|
||||
else ledcWrite(5, backlight_brightness); // Backlight on
|
||||
}
|
||||
}
|
28
Platformio/src/hardware/tft.h
Normal file
28
Platformio/src/hardware/tft.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef __TFT_H__
|
||||
#define __TFT_H__
|
||||
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
#include <Adafruit_FT6206.h>
|
||||
|
||||
#define LCD_DC 9 // defined in TFT_eSPI User_Setup.h
|
||||
#define LCD_CS 5
|
||||
#define LCD_MOSI 23
|
||||
#define LCD_SCK 18
|
||||
#define LCD_BL 4
|
||||
#define LCD_EN 10
|
||||
|
||||
#define SCL 22
|
||||
#define SDA 19
|
||||
|
||||
// LCD declarations
|
||||
extern TFT_eSPI tft;
|
||||
#define screenWidth 240
|
||||
#define screenHeight 320
|
||||
extern Adafruit_FT6206 touch;
|
||||
extern TS_Point touchPoint;
|
||||
extern byte backlight_brightness;
|
||||
|
||||
void init_tft(void);
|
||||
void update_backligthBrighness(void);
|
||||
|
||||
#endif /*__TFT_H__*/
|
10
Platformio/src/hardware/user_led.cpp
Normal file
10
Platformio/src/hardware/user_led.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <Arduino.h>
|
||||
#include "hardware/user_led.h"
|
||||
|
||||
void init_userled(void) {
|
||||
pinMode(USER_LED, OUTPUT);
|
||||
digitalWrite(USER_LED, LOW);
|
||||
}
|
||||
void update_userled(void) {
|
||||
digitalWrite(USER_LED, millis() % 1000 > 500);
|
||||
}
|
9
Platformio/src/hardware/user_led.h
Normal file
9
Platformio/src/hardware/user_led.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __USER_LED_H__
|
||||
#define __USER_LED_H__
|
||||
|
||||
#define USER_LED 2
|
||||
|
||||
void init_userled(void);
|
||||
void update_userled(void);
|
||||
|
||||
#endif /*__USER_LED_H__*/
|
File diff suppressed because it is too large
Load diff
37
Platformio/src/preferencesStorage.cpp
Normal file
37
Platformio/src/preferencesStorage.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "preferencesStorage.h"
|
||||
#include "hardware/sleep.h"
|
||||
#include "hardware/tft.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
#include "commandHandler.h"
|
||||
#include "scenes/sceneHandler.h"
|
||||
|
||||
Preferences preferences;
|
||||
|
||||
void init_preferences(void) {
|
||||
// Restore settings from internal flash memory
|
||||
preferences.begin("settings", false);
|
||||
if(preferences.getBool("alreadySetUp")){
|
||||
wakeupByIMUEnabled = preferences.getBool("wkpByIMU");
|
||||
actualSleepTimeout = preferences.getUInt("slpTimeout");
|
||||
backlight_brightness = preferences.getUChar("blBrightness");
|
||||
currentScreen = preferences.getUChar("currentScreen");
|
||||
currentScene = std::string(preferences.getString("currentScene").c_str());
|
||||
|
||||
// Serial.printf("Preferences restored: brightness %d, screen %d, scene %s\r\n", backlight_brightness, currentScreen, currentScene.c_str());
|
||||
} else {
|
||||
// Serial.printf("No preferences to restore\r\n");
|
||||
}
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
void save_preferences(void) {
|
||||
preferences.begin("settings", false);
|
||||
preferences.putBool("wkpByIMU", wakeupByIMUEnabled);
|
||||
preferences.putUInt("slpTimeout", actualSleepTimeout);
|
||||
preferences.putUChar("blBrightness", backlight_brightness);
|
||||
preferences.putUChar("currentScreen", currentScreen);
|
||||
preferences.putString("currentScene", currentScene.c_str());
|
||||
if(!preferences.getBool("alreadySetUp")) preferences.putBool("alreadySetUp", true);
|
||||
preferences.end();
|
||||
}
|
||||
|
11
Platformio/src/preferencesStorage.h
Normal file
11
Platformio/src/preferencesStorage.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef __PREFERENCESSTORAGE_H__
|
||||
#define __PREFERENCESSTORAGE_H__
|
||||
|
||||
#include <Preferences.h>
|
||||
|
||||
extern Preferences preferences;
|
||||
|
||||
void init_preferences(void);
|
||||
void save_preferences(void);
|
||||
|
||||
#endif /*__PREFERENCESSTORAGE_H__*/
|
55
Platformio/src/scenes/sceneHandler.cpp
Normal file
55
Platformio/src/scenes/sceneHandler.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <string>
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "commandHandler.h"
|
||||
#include "gui_general_and_keys/guiBase.h"
|
||||
|
||||
std::string currentScene = "";
|
||||
|
||||
void handleScene(std::string command, commandData commandData, std::string additionalPayload = "") {
|
||||
|
||||
auto current = commandData.commandPayloads.begin();
|
||||
std::string scene_name = *current;
|
||||
|
||||
// check if we know the new scene
|
||||
if (!sceneExists(scene_name)) {
|
||||
Serial.printf("scene: cannot start scene %s, because it is unknown\r\n", scene_name.c_str());
|
||||
return;
|
||||
} else {
|
||||
Serial.printf("scene: will switch from old scene %s to new scene %s\r\n", currentScene.c_str(), scene_name.c_str());
|
||||
}
|
||||
|
||||
lv_label_set_text(SceneLabel, "changing...");
|
||||
gui_loop();
|
||||
|
||||
// end old scene
|
||||
if (!sceneExists(currentScene) && (currentScene != "")) {
|
||||
Serial.printf("scene: WARNING: cannot end scene %s, because it is unknown\r\n", currentScene.c_str());
|
||||
|
||||
} else {
|
||||
if (currentScene != "") {
|
||||
Serial.printf("scene: will call end sequence for scene %s\r\n", currentScene.c_str());
|
||||
scene_end_sequence_from_registry(currentScene);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// start new scene
|
||||
Serial.printf("scene: will call start sequence for scene %s\r\n", scene_name.c_str());
|
||||
scene_start_sequence_from_registry(scene_name);
|
||||
|
||||
currentScene = scene_name;
|
||||
|
||||
lv_label_set_text(SceneLabel, currentScene.c_str());
|
||||
|
||||
Serial.printf("scene: scene handling finished, new scene %s is active\r\n", currentScene.c_str());
|
||||
}
|
||||
|
||||
void setLabelCurrentScene() {
|
||||
lv_label_set_text(SceneLabel, currentScene.c_str());
|
||||
}
|
12
Platformio/src/scenes/sceneHandler.h
Normal file
12
Platformio/src/scenes/sceneHandler.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __SCENEHANDLER_H__
|
||||
#define __SCENEHANDLER_H__
|
||||
|
||||
#include <string>
|
||||
#include "commandHandler.h"
|
||||
|
||||
extern std::string currentScene; // Current scene that is active
|
||||
|
||||
void handleScene(std::string command, commandData commandData, std::string additionalPayload = "");
|
||||
void setLabelCurrentScene();
|
||||
|
||||
#endif /*__SCENEHANDLER_H__*/
|
167
Platformio/src/scenes/sceneRegistry.cpp
Normal file
167
Platformio/src/scenes/sceneRegistry.cpp
Normal file
|
@ -0,0 +1,167 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
std::map<char, repeatModes> key_repeatModes_default {
|
||||
{'o', SHORT },
|
||||
{'=', SHORT }, {'<', SHORTorLONG }, {'p', SHORT }, {'>', SHORTorLONG },
|
||||
{'c', SHORT }, {'i', SHORT },
|
||||
{'u', SHORT },
|
||||
{'l', SHORT }, {'k', SHORT }, {'r', SHORT },
|
||||
{'d', SHORT },
|
||||
{'b', SHORT }, {'s', SHORT },
|
||||
{'+', SHORT_REPEATED}, {'m', SHORT }, {'^', SHORT },
|
||||
{'-', SHORT_REPEATED}, {'e', SHORT }, {'v', SHORT },
|
||||
{'1', SHORT }, {'2', SHORT }, {'3', SHORT }, {'4', SHORT },
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_short_default {
|
||||
{'o', SCENE_ALLOFF},
|
||||
/*{'=', COMMAND_UNKNOWN},*/ /*{'<', COMMAND_UNKNOWN},*/ /*{'p', COMMAND_UNKNOWN},*/ /*{'>', COMMAND_UNKNOWN},*/
|
||||
/*{'c', COMMAND_UNKNOWN}, */ /*{'i', COMMAND_UNKNOWN},*/
|
||||
/*{'u', COMMAND_UNKNOWN},*/
|
||||
/*{'l', COMMAND_UNKNOWN},*/ /*{'k', COMMAND_UNKNOWN},*/ /*{'r', COMMAND_UNKNOWN},*/
|
||||
/*{'d', COMMAND_UNKNOWN},*/
|
||||
/* {'b', COMMAND_UNKNOWN},*/ /*{'s', COMMAND_UNKNOWN},*/
|
||||
{'+', YAMAHA_VOL_PLUS}, {'m', YAMAHA_MUTE_TOGGLE}, /*{'^', COMMAND_UNKNOWN},*/
|
||||
{'-', YAMAHA_VOL_MINUS}, /*{'e', COMMAND_UNKNOWN},*/ /*{'v', COMMAND_UNKNOWN},*/
|
||||
{'1', SCENE_TV}, {'2', SCENE_FIRETV}, {'3', SCENE_CHROMECAST}, {'4', YAMAHA_STANDARD},
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_long_default {
|
||||
|
||||
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work
|
||||
struct scene_definition {
|
||||
scene_start_sequence this_scene_start_sequence;
|
||||
scene_end_sequence this_scene_end_sequence;
|
||||
key_repeatModes this_key_repeatModes;
|
||||
key_commands_short this_key_commands_short;
|
||||
key_commands_long this_key_commands_long;
|
||||
};
|
||||
|
||||
std::map<std::string, scene_definition> registered_scenes;
|
||||
|
||||
void register_scene(
|
||||
std::string a_scene_name,
|
||||
scene_start_sequence a_scene_start_sequence,
|
||||
scene_end_sequence a_scene_end_sequence,
|
||||
key_repeatModes a_key_repeatModes,
|
||||
key_commands_short a_key_commands_short,
|
||||
key_commands_long a_key_commands_long) {
|
||||
|
||||
registered_scenes[a_scene_name] = scene_definition{
|
||||
a_scene_start_sequence,
|
||||
a_scene_end_sequence,
|
||||
a_key_repeatModes,
|
||||
a_key_commands_short,
|
||||
a_key_commands_long
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool sceneExists(std::string sceneName) {
|
||||
return (registered_scenes.count(sceneName) > 0);
|
||||
}
|
||||
|
||||
void scene_start_sequence_from_registry(std::string sceneName) {
|
||||
try {
|
||||
registered_scenes.at(sceneName).this_scene_start_sequence();
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Serial.printf("scene_start_sequence_from_registry: internal error, sceneName not registered\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void scene_end_sequence_from_registry(std::string sceneName) {
|
||||
try {
|
||||
registered_scenes.at(sceneName).this_scene_end_sequence();
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Serial.printf("scene_end_sequence_from_registry: internal error, sceneName not registered\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
repeatModes get_key_repeatMode(std::string sceneName, char keyChar) {
|
||||
try {
|
||||
// look if the map of the current scene has a definition for it
|
||||
if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_repeatModes->count(keyChar) > 0)) {
|
||||
// Serial.printf("get_key_repeatMode: will use key from scene %s\r\n", sceneName.c_str());
|
||||
return registered_scenes.at(sceneName).this_key_repeatModes->at(keyChar);
|
||||
|
||||
// look if there is a default definition
|
||||
} else if (key_repeatModes_default.count(keyChar) > 0) {
|
||||
// Serial.printf("get_key_repeatMode: will use default key\r\n");
|
||||
return key_repeatModes_default.at(keyChar);
|
||||
|
||||
// no key definition found
|
||||
} else {
|
||||
// Serial.printf("get_key_repeatMode: WARNING no key definition found\r\n");
|
||||
return REPEAT_MODE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Serial.printf("get_key_repeatMode: internal error, sceneName not registered\r\n");
|
||||
return REPEAT_MODE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_command_short(std::string sceneName, char keyChar) {
|
||||
try {
|
||||
// look if the map of the current scene has a definition for it
|
||||
if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_short->count(keyChar) > 0)) {
|
||||
Serial.printf("get_command_short: will use key from scene %s\r\n", sceneName.c_str());
|
||||
return registered_scenes.at(sceneName).this_key_commands_short->at(keyChar);
|
||||
|
||||
// look if there is a default definition
|
||||
} else if (key_commands_short_default.count(keyChar) > 0) {
|
||||
Serial.printf("get_command_short: will use default key\r\n");
|
||||
return key_commands_short_default.at(keyChar);
|
||||
|
||||
// no key definition found
|
||||
} else {
|
||||
Serial.printf("get_command_short: WARNING no key definition found\r\n");
|
||||
return COMMAND_UNKNOWN;
|
||||
}
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Serial.printf("get_command_short: internal error, sceneName not registered\r\n");
|
||||
return COMMAND_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string get_command_long(std::string sceneName, char keyChar) {
|
||||
try {
|
||||
// look if the map of the current scene has a definition for it
|
||||
if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_long->count(keyChar) > 0)) {
|
||||
Serial.printf("get_command_long: will use key from scene %s\r\n", sceneName.c_str());
|
||||
return registered_scenes.at(sceneName).this_key_commands_long->at(keyChar);
|
||||
|
||||
// look if there is a default definition
|
||||
} else if (key_commands_long_default.count(keyChar) > 0) {
|
||||
Serial.printf("get_command_long: will use default key\r\n");
|
||||
return key_commands_long_default.at(keyChar);
|
||||
|
||||
// no key definition found
|
||||
} else {
|
||||
Serial.printf("get_command_long: WARNING no key definition found\r\n");
|
||||
return COMMAND_UNKNOWN;
|
||||
}
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Serial.printf("get_command_long: internal error, sceneName not registered\r\n");
|
||||
return COMMAND_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
30
Platformio/src/scenes/sceneRegistry.h
Normal file
30
Platformio/src/scenes/sceneRegistry.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef __SCENEREGISTRY_H__
|
||||
#define __SCENEREGISTRY_H__
|
||||
|
||||
#include <map>
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
|
||||
typedef void (*scene_start_sequence)(void);
|
||||
typedef void (*scene_end_sequence)(void);
|
||||
typedef std::map<char, repeatModes> *key_repeatModes;
|
||||
typedef std::map<char, std::string> *key_commands_short;
|
||||
typedef std::map<char, std::string> *key_commands_long;
|
||||
|
||||
void register_scene(
|
||||
std::string a_scene_name,
|
||||
scene_start_sequence a_scene_start_sequence,
|
||||
scene_end_sequence a_scene_end_sequence,
|
||||
key_repeatModes a_key_repeatModes,
|
||||
key_commands_short a_key_commands_short,
|
||||
key_commands_long a_key_commands_long);
|
||||
|
||||
#define COMMAND_UNKNOWN "command_unknown"
|
||||
|
||||
bool sceneExists(std::string sceneName);
|
||||
void scene_start_sequence_from_registry(std::string sceneName);
|
||||
void scene_end_sequence_from_registry(std::string sceneName);
|
||||
repeatModes get_key_repeatMode(std::string sceneName, char keyChar);
|
||||
std::string get_command_short(std::string sceneName, char keyChar);
|
||||
std::string get_command_long(std::string sceneName, char keyChar);
|
||||
|
||||
#endif /*__SCENEREGISTRY_H__*/
|
70
Platformio/src/scenes/scene_TV.cpp
Normal file
70
Platformio/src/scenes/scene_TV.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <map>
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
std::map<char, repeatModes> key_repeatModes_TV {
|
||||
|
||||
{'=', SHORT_REPEATED}, {'<', SHORT }, {'p', SHORT }, {'>', SHORT_REPEATED },
|
||||
{'c', SHORT }, {'i', SHORT },
|
||||
{'u', SHORT_REPEATED},
|
||||
{'l', SHORT_REPEATED}, {'k', SHORT}, {'r', SHORT_REPEATED},
|
||||
{'d', SHORT_REPEATED},
|
||||
{'s', SHORT },
|
||||
{'^', SHORT },
|
||||
{'v', SHORT },
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_short_TV {
|
||||
|
||||
{'=', SAMSUNG_REWIND}, {'<', SAMSUNG_PAUSE}, {'p', SAMSUNG_PLAY}, {'>', SAMSUNG_FASTFORWARD},
|
||||
{'c', SAMSUNG_GUIDE}, {'i', SAMSUNG_MENU},
|
||||
{'u', SAMSUNG_UP},
|
||||
{'l', SAMSUNG_LEFT}, {'k', SAMSUNG_SELECT}, {'r', SAMSUNG_RIGHT},
|
||||
{'d', SAMSUNG_DOWN},
|
||||
{'s', SAMSUNG_EXIT},
|
||||
{'^', SAMSUNG_CHANNEL_UP},
|
||||
{'v', SAMSUNG_CHANNEL_DOWN},
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_long_TV {
|
||||
|
||||
|
||||
};
|
||||
|
||||
void scene_start_sequence_TV(void) {
|
||||
executeCommand(SAMSUNG_POWER_ON);
|
||||
delay(500);
|
||||
executeCommand(YAMAHA_POWER_ON);
|
||||
delay(1500);
|
||||
executeCommand(YAMAHA_INPUT_DVD);
|
||||
delay(3000);
|
||||
executeCommand(SAMSUNG_INPUT_TV);
|
||||
|
||||
}
|
||||
|
||||
void scene_end_sequence_TV(void) {
|
||||
|
||||
}
|
||||
|
||||
std::string scene_name_TV = "TV";
|
||||
|
||||
void register_scene_TV(void){
|
||||
register_scene(
|
||||
scene_name_TV,
|
||||
& scene_start_sequence_TV,
|
||||
& scene_end_sequence_TV,
|
||||
& key_repeatModes_TV,
|
||||
& key_commands_short_TV,
|
||||
& key_commands_long_TV);
|
||||
|
||||
commands[SCENE_TV] = makeCommandData(SCENE, {scene_name_TV});
|
||||
}
|
9
Platformio/src/scenes/scene_TV.h
Normal file
9
Platformio/src/scenes/scene_TV.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __SCENE_TV_H__
|
||||
#define __SCENE_TV_H__
|
||||
|
||||
#define SCENE_TV "Scene_tv"
|
||||
|
||||
extern std::string scene_name_TV;
|
||||
void register_scene_TV(void);
|
||||
|
||||
#endif /*__SCENE_TV_H__*/
|
81
Platformio/src/scenes/scene_allOff.cpp
Normal file
81
Platformio/src/scenes/scene_allOff.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#include <map>
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
std::map<char, repeatModes> key_repeatModes_allOff {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_short_allOff {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_long_allOff {
|
||||
|
||||
|
||||
};
|
||||
|
||||
void scene_start_sequence_allOff(void) {
|
||||
executeCommand(SAMSUNG_POWER_OFF);
|
||||
delay(500);
|
||||
executeCommand(YAMAHA_POWER_OFF);
|
||||
delay(500);
|
||||
// repeat IR to be sure
|
||||
executeCommand(SAMSUNG_POWER_OFF);
|
||||
delay(500);
|
||||
executeCommand(YAMAHA_POWER_OFF);
|
||||
delay(500);
|
||||
// repeat IR to be sure
|
||||
executeCommand(SAMSUNG_POWER_OFF);
|
||||
delay(500);
|
||||
executeCommand(YAMAHA_POWER_OFF);
|
||||
delay(500);
|
||||
// you cannot power off FireTV, but at least you can stop the currently running app
|
||||
executeCommand(KEYBOARD_HOME);
|
||||
delay(500);
|
||||
executeCommand(KEYBOARD_HOME);
|
||||
|
||||
}
|
||||
|
||||
void scene_end_sequence_allOff(void) {
|
||||
|
||||
}
|
||||
|
||||
std::string scene_name_allOff = "Off";
|
||||
|
||||
void register_scene_allOff(void){
|
||||
register_scene(
|
||||
scene_name_allOff,
|
||||
& scene_start_sequence_allOff,
|
||||
& scene_end_sequence_allOff,
|
||||
& key_repeatModes_allOff,
|
||||
& key_commands_short_allOff,
|
||||
& key_commands_long_allOff);
|
||||
|
||||
commands[SCENE_ALLOFF] = makeCommandData(SCENE, {scene_name_allOff});
|
||||
}
|
9
Platformio/src/scenes/scene_allOff.h
Normal file
9
Platformio/src/scenes/scene_allOff.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __SCENE_ALLOFF_H__
|
||||
#define __SCENE_ALLOFF_H__
|
||||
|
||||
#define SCENE_ALLOFF "Scene_allOff"
|
||||
|
||||
extern std::string scene_name_allOff;
|
||||
void register_scene_allOff(void);
|
||||
|
||||
#endif /*__SCENE_ALLOFF_H__*/
|
70
Platformio/src/scenes/scene_chromecast.cpp
Normal file
70
Platformio/src/scenes/scene_chromecast.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <map>
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
std::map<char, repeatModes> key_repeatModes_chromecast {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_short_chromecast {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_long_chromecast {
|
||||
|
||||
|
||||
};
|
||||
|
||||
void scene_start_sequence_chromecast(void) {
|
||||
executeCommand(SAMSUNG_POWER_ON);
|
||||
delay(500);
|
||||
executeCommand(YAMAHA_POWER_ON);
|
||||
delay(1500);
|
||||
executeCommand(YAMAHA_INPUT_DVD);
|
||||
delay(3000);
|
||||
executeCommand(SAMSUNG_INPUT_HDMI_1);
|
||||
|
||||
}
|
||||
|
||||
void scene_end_sequence_chromecast(void) {
|
||||
|
||||
}
|
||||
|
||||
std::string scene_name_chromecast = "Chromecast";
|
||||
|
||||
void register_scene_chromecast(void){
|
||||
register_scene(
|
||||
scene_name_chromecast,
|
||||
& scene_start_sequence_chromecast,
|
||||
& scene_end_sequence_chromecast,
|
||||
& key_repeatModes_chromecast,
|
||||
& key_commands_short_chromecast,
|
||||
& key_commands_long_chromecast);
|
||||
|
||||
commands[SCENE_CHROMECAST] = makeCommandData(SCENE, {scene_name_chromecast});
|
||||
}
|
9
Platformio/src/scenes/scene_chromecast.h
Normal file
9
Platformio/src/scenes/scene_chromecast.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __SCENE_CHROMECAST_H__
|
||||
#define __SCENE_CHROMECAST_H__
|
||||
|
||||
#define SCENE_CHROMECAST "Scene_chromecast"
|
||||
|
||||
extern std::string scene_name_chromecast;
|
||||
void register_scene_chromecast(void);
|
||||
|
||||
#endif /*__SCENE_CHROMECAST_H__*/
|
79
Platformio/src/scenes/scene_fireTV.cpp
Normal file
79
Platformio/src/scenes/scene_fireTV.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include <map>
|
||||
#include "gui_general_and_keys/keys.h"
|
||||
#include "device_samsungTV/device_samsungTV.h"
|
||||
#include "device_yamahaAmp/device_yamahaAmp.h"
|
||||
#include "scenes/sceneRegistry.h"
|
||||
#include "scenes/scene_allOff.h"
|
||||
#include "scenes/scene_TV.h"
|
||||
#include "scenes/scene_fireTV.h"
|
||||
#include "scenes/scene_chromecast.h"
|
||||
#include "commandHandler.h"
|
||||
|
||||
std::map<char, repeatModes> key_repeatModes_fireTV {
|
||||
|
||||
{'<', SHORTorLONG }, {'p', SHORT }, {'>', SHORTorLONG },
|
||||
{'c', SHORT }, {'i', SHORT },
|
||||
{'u', SHORT },
|
||||
{'l', SHORT }, {'k', SHORT }, {'r', SHORT },
|
||||
{'d', SHORT },
|
||||
{'s', SHORT },
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_short_fireTV {
|
||||
|
||||
{'<', KEYBOARD_REWIND}, {'p', KEYBOARD_PLAYPAUSE}, {'>', KEYBOARD_FASTFORWARD},
|
||||
{'c', KEYBOARD_HOME}, {'i', KEYBOARD_MENU},
|
||||
{'u', KEYBOARD_UP},
|
||||
{'l', KEYBOARD_LEFT}, {'k', KEYBOARD_SELECT}, {'r', KEYBOARD_RIGHT},
|
||||
{'d', KEYBOARD_DOWN},
|
||||
{'s', KEYBOARD_BACK},
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
std::map<char, std::string> key_commands_long_fireTV {
|
||||
{'<', KEYBOARD_REWIND_LONG},
|
||||
{'>', KEYBOARD_FASTFORWARD_LONG},
|
||||
};
|
||||
|
||||
void scene_start_sequence_fireTV(void) {
|
||||
executeCommand(SAMSUNG_POWER_ON);
|
||||
delay(500);
|
||||
executeCommand(YAMAHA_POWER_ON);
|
||||
delay(1500);
|
||||
executeCommand(YAMAHA_INPUT_DTV);
|
||||
delay(3000);
|
||||
executeCommand(SAMSUNG_INPUT_HDMI_2);
|
||||
delay(100);
|
||||
|
||||
executeCommand(KEYBOARD_HOME);
|
||||
delay(500);
|
||||
executeCommand(KEYBOARD_HOME);
|
||||
|
||||
}
|
||||
|
||||
void scene_end_sequence_fireTV(void) {
|
||||
// you cannot power off FireTV, but at least you can stop the currently running app
|
||||
executeCommand(KEYBOARD_HOME);
|
||||
delay(500);
|
||||
executeCommand(KEYBOARD_HOME);
|
||||
|
||||
}
|
||||
|
||||
std::string scene_name_fireTV = "Fire TV";
|
||||
|
||||
void register_scene_fireTV(void){
|
||||
register_scene(
|
||||
scene_name_fireTV,
|
||||
& scene_start_sequence_fireTV,
|
||||
& scene_end_sequence_fireTV,
|
||||
& key_repeatModes_fireTV,
|
||||
& key_commands_short_fireTV,
|
||||
& key_commands_long_fireTV);
|
||||
|
||||
commands[SCENE_FIRETV] = makeCommandData(SCENE, {scene_name_fireTV});
|
||||
}
|
9
Platformio/src/scenes/scene_fireTV.h
Normal file
9
Platformio/src/scenes/scene_fireTV.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __SCENE_FIRETV_H__
|
||||
#define __SCENE_FIRETV_H__
|
||||
|
||||
#define SCENE_FIRETV "Scene_firetv"
|
||||
|
||||
extern std::string scene_name_fireTV;
|
||||
void register_scene_fireTV(void);
|
||||
|
||||
#endif /*__SCENE_FIRETV_H__*/
|
19
Platformio/src/secrets.h
Normal file
19
Platformio/src/secrets.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Before changing anything in this file, consider to copy file "secrets_override_example.h" to file "secrets_override.h" and to do your changes there.
|
||||
Doing so, you will
|
||||
- keep your credentials secret
|
||||
- most likely never have conflicts with new versions of this file
|
||||
*/
|
||||
#define WIFI_SSID "YourWifiSSID" // override it in file "secrets_override.h"
|
||||
#define WIFI_PASSWORD "YourWifiPassword" // override it in file "secrets_override.h"
|
||||
|
||||
#define MQTT_SERVER "IPAddressOfYourBroker" // override it in file "secrets_override.h"
|
||||
#define MQTT_SERVER_PORT 1883 // override it in file "secrets_override.h"
|
||||
#define MQTT_USER "" // override it in file "secrets_override.h"
|
||||
#define MQTT_PASS "" // override it in file "secrets_override.h"
|
||||
#define MQTT_CLIENTNAME "OMOTE" // override it in file "secrets_override.h"
|
||||
|
||||
// --- include override settings from seperate file ---------------------------------------------------------------------------------------------------------------
|
||||
#if __has_include("secrets_override.h")
|
||||
#include "secrets_override.h"
|
||||
#endif
|
12
Platformio/src/secrets_override_example.h
Normal file
12
Platformio/src/secrets_override_example.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
If you add additional overrides here, you have to
|
||||
1. first add #undef
|
||||
2. add new #define
|
||||
*/
|
||||
#undef WIFI_SSID
|
||||
#undef WIFI_PASSWORD
|
||||
#undef MQTT_SERVER
|
||||
|
||||
#define WIFI_SSID "YourWifiSSID" // override here
|
||||
#define WIFI_PASSWORD "YourWifiPassword" // override here
|
||||
#define MQTT_SERVER "IPAddressOfYourBroker" // override here
|
|
@ -1,3 +1,6 @@
|
|||
# Changes in this fork
|
||||
For changes in this fork, please see https://github.com/CoretechR/OMOTE/discussions/58
|
||||
|
||||
# OMOTE - Open Universal Remote
|
||||
|
||||
![](P1030424_small.jpg)
|
||||
|
@ -103,4 +106,4 @@ Maximilian Kern - [kernm.de](https://kernm.de)
|
|||
Project Page on Hackaday.io: [https://hackaday.io/project/191752-omote-diy-universal-remote](https://hackaday.io/project/191752-omote-diy-universal-remote)
|
||||
|
||||
|
||||
[link1]: https://discord.gg/5PnYFAsKsG
|
||||
[link1]: https://discord.gg/5PnYFAsKsG
|
||||
|
|
Loading…
Reference in a new issue