From 4c179028defe350050f4b6a8e57330f403467667 Mon Sep 17 00:00:00 2001 From: sivar2311 Date: Sun, 27 Mar 2022 12:28:23 +0200 Subject: [PATCH 1/2] Codechanges for Version 1.0.0 --- .github/workflows/build.yml | 2 +- doc/ble_advertising.md | 2 +- .../MultiReceiver.ino => Receiver.ino} | 31 ++-- .../SingleReceiver/SingleReceiver.ino | 68 -------- examples/Sender/Sender.ino | 57 ++++--- library.json | 2 +- library.properties | 2 +- readme.md | 157 +----------------- readme_de.md | 157 +----------------- src/BLERemoteControlInfo.h | 33 ++-- src/BLERemoteControlReceiver.h | 100 +++++------ src/BLERemoteControlSender.h | 105 +++++++++--- src/BLERemoteControlStorage.h | 89 +--------- src/NVSRemoteControlStorage.h | 78 +++++---- 14 files changed, 261 insertions(+), 622 deletions(-) rename examples/Receiver/{MultiReceiver/MultiReceiver.ino => Receiver.ino} (69%) delete mode 100644 examples/Receiver/SingleReceiver/SingleReceiver.ino diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ef9ade..97cbd80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - example: [examples/Receiver/SingleReceiver, examples/Receiver/MultiReceiver, examples/Sender] + example: [examples/Receiver, examples/Sender] steps: diff --git a/doc/ble_advertising.md b/doc/ble_advertising.md index 1aeeb23..61b6682 100644 --- a/doc/ble_advertising.md +++ b/doc/ble_advertising.md @@ -5,7 +5,7 @@ | Name: | BLE advertisement flags | length of the
next field | type of the
next field | Manufacturer
data | |----------:|:-----------------------:|:---------------------------:|:-----------------------------:|:--------------------:| | *Length*: | 3 Bytes | 1 Byte | 1 Byte | 20 Bytes | -| *Value*: | `0x02` `0x01` `0x06` | `0x15` | `0xFF`
(manufacturer data) | [Data](#data) | +| *Value*: | `0x02` `0x01` `0x06` | `0x15` | `0xFF`
(manufacturer data) | [Data](#data) | | | **fixed** | **fixed**
| **fixed** | *variable* | **Note:** diff --git a/examples/Receiver/MultiReceiver/MultiReceiver.ino b/examples/Receiver/Receiver.ino similarity index 69% rename from examples/Receiver/MultiReceiver/MultiReceiver.ino rename to examples/Receiver/Receiver.ino index 2552ca7..a7869fe 100644 --- a/examples/Receiver/MultiReceiver/MultiReceiver.ino +++ b/examples/Receiver/Receiver.ino @@ -5,12 +5,15 @@ NVSRemoteControlStorage storage; BLERemoteControlReceiver receiver; -#define COMMAND_LED_ON 0x0001 -#define COMMAND_LED_OFF 0x0002 +const uint32_t COMMAND_LED_ON = 0x0001; +const uint32_t COMMAND_LED_OFF = 0x0002; -#define GPIO_LED 16 -#define GPIO_SYNC_BUTTON 34 -#define PRESSED HIGH +const int GPIO_LED = 16; +const int GPIO_SYNC_BUTTON = 34; + +const bool PRESSED = HIGH; + +const uint32_t SHARED_SYNCHRONIZATION_PIN = 123456; void turn_on_led() { digitalWrite(GPIO_LED, HIGH); @@ -31,13 +34,10 @@ void handle_sync_button() { bool sync_button = digitalRead(GPIO_SYNC_BUTTON); if (sync_button == PRESSED) { - if (receiver.is_synchronizing()) { - receiver.stop_synchronizing(); - } else { - receiver.start_synchronizing(); - } - delay(150); // simple debounce + receiver.start_synchronizing(10); } + + delay(150); // simple button debounce } void setup_led() { @@ -48,18 +48,19 @@ void setup_button() { pinMode(GPIO_SYNC_BUTTON, INPUT); } -void setup_receiver() { +void setup_storage() { storage.begin("ble_remote"); - storage.load(); +} +void setup_receiver() { receiver.on_command(handle_command); - receiver.set_sync_pin(123456); - receiver.begin(&storage); + receiver.begin(&storage, SHARED_SYNCHRONIZATION_PIN); } void setup() { setup_led(); setup_button(); + setup_storage(); setup_receiver(); } diff --git a/examples/Receiver/SingleReceiver/SingleReceiver.ino b/examples/Receiver/SingleReceiver/SingleReceiver.ino deleted file mode 100644 index 2552ca7..0000000 --- a/examples/Receiver/SingleReceiver/SingleReceiver.ino +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include - -NVSRemoteControlStorage storage; -BLERemoteControlReceiver receiver; - -#define COMMAND_LED_ON 0x0001 -#define COMMAND_LED_OFF 0x0002 - -#define GPIO_LED 16 -#define GPIO_SYNC_BUTTON 34 -#define PRESSED HIGH - -void turn_on_led() { - digitalWrite(GPIO_LED, HIGH); -} - -void turn_off_led() { - digitalWrite(GPIO_LED, LOW); -} - -void handle_command(ble_remote_command_info_t* command_info) { - uint16_t command = command_info->command; - - if (command == COMMAND_LED_ON) turn_on_led(); - if (command == COMMAND_LED_OFF) turn_off_led(); -} - -void handle_sync_button() { - bool sync_button = digitalRead(GPIO_SYNC_BUTTON); - - if (sync_button == PRESSED) { - if (receiver.is_synchronizing()) { - receiver.stop_synchronizing(); - } else { - receiver.start_synchronizing(); - } - delay(150); // simple debounce - } -} - -void setup_led() { - pinMode(GPIO_LED, OUTPUT); -} - -void setup_button() { - pinMode(GPIO_SYNC_BUTTON, INPUT); -} - -void setup_receiver() { - storage.begin("ble_remote"); - storage.load(); - - receiver.on_command(handle_command); - receiver.set_sync_pin(123456); - receiver.begin(&storage); -} - -void setup() { - setup_led(); - setup_button(); - setup_receiver(); -} - -void loop() { - handle_sync_button(); -} \ No newline at end of file diff --git a/examples/Sender/Sender.ino b/examples/Sender/Sender.ino index b51fe45..935e7fb 100644 --- a/examples/Sender/Sender.ino +++ b/examples/Sender/Sender.ino @@ -1,26 +1,35 @@ #include - #include #include NVSRemoteControlStorage storage; -BLERemoteControlSender sender; +BLERemoteControlSender sender; -#define GPIO_BUTTON_ON 34 -#define GPIO_BUTTON_OFF 35 -#define GPIO_BUTTON_SYNC 36 +const int GPIO_BUTTON_ON = 34; +const int GPIO_BUTTON_OFF = 35; +const int GPIO_BUTTON_SYNC = 36; -#define PRESSED HIGH +const bool PRESSED = HIGH; -#define COMMAND_LED_ON 0x0001 -#define COMMAND_LED_OFF 0x0002 +const uint32_t COMMAND_LED_ON = 0x0001; +const uint32_t COMMAND_LED_OFF = 0x0002; +const uint32_t UNIQUE_REMOTE_ID = 0xBEEF; +const int SHARED_SYNCHRONIZATION_PIN = 123456; +const int SYNCHRONIZATION_TIMEOUT = 10; -void setup_storage() { - storage.begin("ble_remote"); - if (!storage.load()) { - storage.add(new ble_remote_control_info_t(0x0001,true)); - storage.save(); +void handle_buttons() { + bool button_on = digitalRead(GPIO_BUTTON_ON); + bool button_off = digitalRead(GPIO_BUTTON_OFF); + bool button_sync = digitalRead(GPIO_BUTTON_SYNC); + + if (button_on == PRESSED) sender.send_command(COMMAND_LED_ON); + if (button_off == PRESSED) sender.send_command(COMMAND_LED_OFF); + if (button_sync == PRESSED) sender.start_synchronizing(SYNCHRONIZATION_TIMEOUT); + + bool a_button_was_pressed = (button_on == PRESSED || button_off == PRESSED || button_sync == PRESSED); + if (a_button_was_pressed) { + delay(150); // simple "debounce" } } @@ -30,23 +39,23 @@ void setup_buttons() { pinMode(GPIO_BUTTON_SYNC, INPUT); } -void handle_buttons() { - bool button_on = digitalRead(GPIO_BUTTON_ON); - bool button_off = digitalRead(GPIO_BUTTON_OFF); - bool button_sync = digitalRead(GPIO_BUTTON_SYNC); - - if (button_on == PRESSED) sender.send_command(COMMAND_LED_ON, storage[0]); - if (button_off == PRESSED) sender.send_command(COMMAND_LED_OFF, storage[0]); - if (button_sync == PRESSED) sender.start_sync(*(storage[0])); +void setup_storage() { + storage.begin("ble_remote"); - if (button_on == PRESSED || button_off == PRESSED || button_sync == PRESSED) { - delay(150); // simple "debounce" + if (storage.exist(UNIQUE_REMOTE_ID) == false) { + storage.add(new ble_remote_control_info_t(UNIQUE_REMOTE_ID, true)); + storage.save(); } } +void setup_sender() { + sender.begin(UNIQUE_REMOTE_ID, &storage, SHARED_SYNCHRONIZATION_PIN); +} + void setup() { setup_buttons(); - sender.begin(); + setup_storage(); + setup_sender(); } void loop() { diff --git a/library.json b/library.json index fb275ed..113a2ae 100644 --- a/library.json +++ b/library.json @@ -13,7 +13,7 @@ "maintainer": true } ], - "version": "0.2.1", + "version": "1.0.0", "frameworks": "arduino", "platforms": [ "espressif32" diff --git a/library.properties b/library.properties index c81c529..893e582 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESP32-BLE-RemoteControl -version=0.2.1 +version=1.0.0 author=Sivar2311 maintainer=Sivar2311 sentence=This library allows you to send and receive simple command messages via Bluetooth Low Energy. diff --git a/readme.md b/readme.md index 9f0a6e3..4119e22 100644 --- a/readme.md +++ b/readme.md @@ -41,158 +41,5 @@ This library depends on [NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduin # Use -## Remote control information - -Each remote control is managed with the structure `ble_remote_control_info_t`. -This contains the ID number of the remote control, the AES key and the rolling code. -It provides two constructors to simplify the instantiation of a remote control. - -### Instancing a remote control information - -Default: - -```C++ - -ble_remote_control_info_t remote ( -/* id */ 0x0001, -/* aes-key */ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00A, 0x00B, 0x0C, 0x0D, 0x0E, 0x0F} -); -``` - -With pre-assigned rolling-code: - -```C++ -ble_remote_control_info_t remote ( -/* id */ 0x0001, -/* aes-key */ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00A, 0x00B, 0x0C, 0x0D, 0x0E, 0x0F}, -/* rolling-code */ 0x1234 -); -``` - -*Note:* -This can be useful if the remote control is to be operated in a very power-saving way and is switched off in the meantime. -The rolling code can, for example, be stored in the EEPROM, NVS or in a file before switching off and reloaded from it after switching on. - -## Sender - -The sending of commands is done by the class 'BLERemoteControlSender'. - -### Instancing the sender - -```C++ -BLERemoteControlSender sender; -``` - -### Sending commands - -The function `send_command` is used to send commands. -The function is passed the command code to be sent of type `uint32_t` in the first parameter. -In the second parameter, a ***pointer*** to the remote control of type `ble_remote_control_info_t` is passed. - -Example: Sending the command code "0x1234" with the previously created remote control - -```C++ -sender.send_command(0x1234, &remote); -``` - -Example: [Sender.ino](/examples/Sender/Sender.ino) - -## Receiver - -Receiving the commands is done by the class 'BLERemoteControlReceiver'. - -### Instancing the receiver - -```C++ -BLERemoteControlReceiver receiver; -``` - -### Adding remote controls - -All (accepted) remote controls must first be added to the receiver. -The function `add_remote_control` is used for this purpose. -The function receives as parameter a ***pointer*** to the remote control of type `ble_remote_control_info_t`. - -```C++ -receiver.add_remote_control(&remote); -``` - -Example: [SingleReceiver.ino](/examples/Receiver/SingleReceiver/SingleReceiver.ino). - -A receiver can receive several remote controls. -To do this, all remote controls to be received must be added to the receiver. - -```C++ -receiver.add_remote_control(&remote_1); -receiver.add_remote_control(&remote_2); -receiver.add_remote_control(&remote_3); -receiver.add_remote_control(&remote_4); -``` - -Example: [MultiReceiver.ino](/examples/Receiver/MultiReceiver/MultiReceiver.ino) - - -### Handling of received commands - -To process commands, a callback function is called when remote control commands are received from the receiver. -The callback function contains as a parameter a ***pointer*** of type `ble_remote_command_info_t` which contains the command and a ***pointer*** to the remote control. - -```C++ -void handle_command(ble_remote_command_info_t* command_info) { - Serial.print("Received command: "); - Serial.print(command_info->command); - Serial.print(" from remote-control with id: "); - Serial.println(command_info->remote_control.id, HEX); -} -``` - -### Assign the callback function for command handling - -```C++ -receiver.on_command(handle_command); -``` - -### Start the receiver - -```C++ -receiver.begin(); -``` - -### Removing remote controls - -A remote control can be removed (e.g. if it has been lost). -The function `remove_remote_control` is used for this purpose. -The function receives as parameter a ***pointer*** to the remote control of type `ble_remote_control_info_t`. - -```C++ -receiver.remove_remote_control(&remote_3); -``` - -### Synchronising a remote control - -The receiver class allows the synchronisation of remote controls. This is necessary if the rolling code of the remote control is smaller than that of the receiver. This can happen, for example, by restarting the remote control without saving and reloading the rolling code (in the remote control of the sender). - -Starting the synchronisation: -```C++ -receiver.sync_remotecontrol(); -``` -The next received command from a remote control is used to update the rolling code in the receiver's remote control information. The command itself is not handled. Subsequently, the synchronisation mode is terminated and the following commands are handled normally. - - -### Synchronisation callback function -Once synchronisation has taken place, the synchronisation callback function is called. -The callback function is passed a ***pointer*** of type `ble_remote_control_info_t` as a parameter, which specifies the synchronised remote control. - -```C++ -void print_sync_info(ble_remote_control_info_t* remote_control) { - Serial.print("Remote Control with id "); - Serial.print(remote_control->id); - Serial.println(" has been synchronized"); -} -``` - -### Assigning the synchronisation callback function - -```C++ -receiver.on_sync(print_sync_info); -``` \ No newline at end of file +This chapter needs to be recreated as there have been fundamental changes. +Until then, please have a look at the [examples](https://github.com/sivar2311/ESP32-BLE-RemoteControl/tree/master/examples). \ No newline at end of file diff --git a/readme_de.md b/readme_de.md index a4a5962..6fa73e5 100644 --- a/readme_de.md +++ b/readme_de.md @@ -41,158 +41,5 @@ Diese Bibliothek ist Abhängig von [NimBLE-Arduino](https://github.com/h2zero/Ni # Benutzung -## Fernbedienungsinformation - -Jede Fernbedienung wird mit der Struktur `ble_remote_control_info_t` verwaltet. -Diese enthält die ID-Nummer der Fernbedienung, den AES-Schlüssel und den Rolling-Code. -Sie stellt zwei Konstruktoren bereit um die Instanziierung einer Fernbedienung zu vereinfachen. - -### Instanziierung einer Fernbedienung - -Standard: - -```C++ - -ble_remote_control_info_t remote ( -/* id */ 0x0001, -/* aes-key */ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00A, 0x00B, 0x0C, 0x0D, 0x0E, 0x0F} -); -``` - -Mit vorbelegtem rolling-code: - -```C++ -ble_remote_control_info_t remote ( -/* id */ 0x0001, -/* aes-key */ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00A, 0x00B, 0x0C, 0x0D, 0x0E, 0x0F}, -/* rolling-code */ 0x1234 -); -``` - -*Notiz:* -Dies kann nützlich sein, wenn die Fernbedienung sehr stromsparend betrieben werden soll und zwischenzeitlich ausgeschaltet wird. -Der Rolling-Code kann z. B. vor dem Ausschalten im EEPROM, NVS oder in einer Datei gespeichert, und nach dem Einschalten daraus wieder geladen werden. - -## Sender - -Das Senden der Befehle wird von der Klasse `BLERemoteControlSender` vorgenommen. - -### Instanzierung des Senders - -```C++ -BLERemoteControlSender sender; -``` - -### Senden von Befehlen - -Zum Senden von Befehlen wird die Funktion `send_command` verwendet. -Der Funktion wird im ersten Parameter der zu sendende Befehls-Code vom typ `uint32_t` übergeben. -Im zweiten Parameter wird ein ***Zeiger*** auf die Fernbedienung vom Typ `ble_remote_control_info_t` übergeben. - -Beispiel: Senden des Befehls-Code "0x1234" mit der zuvor angelegten Fernbedienung - -```C++ -sender.send_command(0x1234, &remote); -``` - -Beispiel: [Sender.ino](/examples/Sender/Sender.ino) - -## Empfänger - -Der Empfang der Befehle wird von der Klasse `BLERemoteControlReceiver` vorgenommen. - -### Instanzierung des Empfängers - -```C++ -BLERemoteControlReceiver receiver; -``` - -### Hinzufügen von Fernbedienungen - -Dem Empfänger müssen zunächst alle (akzeptierten) Fernbedienungen hinzugefügt werden. -Dazu wird die Funktion `add_remote_control` verwendet. -Die Funktion erhält als Parameter ein ***Zeiger*** auf die Fernbedienung vom Typ `ble_remote_control_info_t`. - -```C++ -receiver.add_remote_control(&remote); -``` - -Beispiel: [SingleReceiver.ino](/examples/Receiver/SingleReceiver/SingleReceiver.ino) - -Ein Empfänger kann mehrere Fernbedienungen empfangen. -Dazu müssen dem Empfänger alle zu empfangenden Fernbedienungen hinzugefügt werden. - -```C++ -receiver.add_remote_control(&remote_1); -receiver.add_remote_control(&remote_2); -receiver.add_remote_control(&remote_3); -receiver.add_remote_control(&remote_4); -``` - -Beispiel: [MultiReceiver.ino](/examples/Receiver/MultiReceiver/MultiReceiver.ino) - - -### Behandeln von empfangenen Befehlen - -Zur Verarbeitung von Befehlen wird beim Empfang von Fernbedienungs-Befehlen vom Empfänger eine Rückruffunktion aufgerufen. -Die Rückruffunktion enthält als Parameter einen ***Zeiger*** vom Typ `ble_remote_command_info_t` welche den Befehl und einen ***Zeiger*** auf die Fernbedienung enthält. - -```C++ -void handle_command(ble_remote_command_info_t* command_info) { - Serial.print("Received command: "); - Serial.print(command_info->command); - Serial.print(" from remote-control with id: "); - Serial.println(command_info->remote_control.id, HEX); -} -``` - -### Zuweisen der Rückruf-Funktion für die Befehlsbehandlung - -```C++ -receiver.on_command(handle_command); -``` - -### Starten des Empfängers - -```C++ -receiver.begin(); -``` - -### Entfernen von Fernbedienungen - -Eine Fernbedienung kann entfernt werden (z. B. wenn diese verloren wurde). -Dazu wird die Funktion `remove_remote_control` verwendet. -Die Funktion erhält als Parameter ein ***Zeiger*** auf die Fernbedienung vom Typ `ble_remote_control_info_t`. - -```C++ -receiver.remove_remote_control(&remote_3); -``` - -### Synchronisieren einer Fernbedienung - -Die Empfängerklasse erlaubt das Synchronisieren von Fernbedienungen. Dies ist Notwendig wenn der Rolling-Code der Fernbedienung kleiner als der des Empfängers ist. Das kann z.B. durch einen Neustart der Fernbedienung passieren, ohne dass der Rolling-Code (in der Fernbedienung des Senders) gespeichert und wieder geladen wurde. - -Starten der Synchronisierung: -```C++ -receiver.sync_remotecontrol(); -``` -Der nächste empfangene Befehl einer Fernbedienung wird genutzt um den Rolling-Code in der Fernbedienungsinformation des Empfängers zu aktualisieren. Der Befehl selbst wird dabei nicht behandelt. Anschließend wird der Synchronisationsmodus beendet und folgende Befehle werden normal behandelt. - - -### Synchronisations Rückruf-Funktion -Sobald eine Synchronisation stattgefunden hat wird die Synchronisations Rückruf-Funktion aufgerufen. -Der Rückruf-Funktion wird als Parameter ein ***Zeiger*** vom Typ `ble_remote_control_info_t` übergeben, welche die synchronisierte Fernbedienung spezifiziert. - -```C++ -void print_sync_info(ble_remote_control_info_t* remote_control) { - Serial.print("Remote Control with id "); - Serial.print(remote_control->id); - Serial.println(" has been synchronized"); -} -``` - -### Zuweisen der Synchronisations Rückruf-Funktion - -```C++ -receiver.on_sync(print_sync_info); -``` \ No newline at end of file +Dieses Kapitel muss neu erstellt werden, da sich grundlegende Änderungen ergeben haben. +Bitte schauen Sie sich bis dahin die [Beispiele](https://github.com/sivar2311/ESP32-BLE-RemoteControl/tree/master/examples) an. \ No newline at end of file diff --git a/src/BLERemoteControlInfo.h b/src/BLERemoteControlInfo.h index 0e91497..67774c0 100644 --- a/src/BLERemoteControlInfo.h +++ b/src/BLERemoteControlInfo.h @@ -13,6 +13,7 @@ class __attribute__((packed)) ble_remote_control_info_t { ble_remote_control_info_t(uint16_t id); ble_remote_control_info_t(uint16_t id, bool new_key); ble_remote_control_info_t(uint16_t id, std::initializer_list aes_key, uint32_t rolling_code = 1); + String toString(); public: uint16_t id; @@ -23,22 +24,25 @@ class __attribute__((packed)) ble_remote_control_info_t { void init_aes_key_from_initializer_list(std::initializer_list& src); }; -ble_remote_control_info_t::ble_remote_control_info_t() : id(0), aes_key{0}, rolling_code(0) {} +ble_remote_control_info_t::ble_remote_control_info_t() + : id(0), aes_key{0}, rolling_code(0) {} ble_remote_control_info_t::ble_remote_control_info_t(const ble_remote_control_info_t& other) { - this->id = other.id; - this->rolling_code = other.rolling_code; - memcpy(this->aes_key, other.aes_key, sizeof(this->aes_key)); + this->id = other.id; + this->rolling_code = other.rolling_code; + memcpy(this->aes_key, other.aes_key, sizeof(this->aes_key)); } -ble_remote_control_info_t::ble_remote_control_info_t(uint16_t id) : id(id), aes_key{0}, rolling_code(1) {} +ble_remote_control_info_t::ble_remote_control_info_t(uint16_t id) + : id(id), aes_key{0}, rolling_code(1) {} -ble_remote_control_info_t::ble_remote_control_info_t(uint16_t id, bool new_key) : id(id), rolling_code(1) { - if (new_key) { - for (size_t i=0; i < sizeof(aes_key_t); i++) { - aes_key[i] = random(0xFF); +ble_remote_control_info_t::ble_remote_control_info_t(uint16_t id, bool new_key) + : id(id), rolling_code(1) { + if (new_key) { + for (size_t i = 0; i < sizeof(aes_key_t); i++) { + aes_key[i] = random(0xFF); + } } - } } ble_remote_control_info_t::ble_remote_control_info_t(uint16_t id, std::initializer_list aes_key, uint32_t rolling_code) @@ -57,3 +61,12 @@ void ble_remote_control_info_t::init_aes_key_from_initializer_list(std::initiali } } } + +String ble_remote_control_info_t::toString() { + char buf[256]; + snprintf(buf, 256, "id: 0x%04x, rc: 0x%08x, aes-key: [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", + id, rolling_code, + aes_key[0], aes_key[1], aes_key[2], aes_key[3], aes_key[4], aes_key[5], aes_key[6], aes_key[7], + aes_key[8], aes_key[9], aes_key[10], aes_key[11], aes_key[12], aes_key[13], aes_key[14], aes_key[15]); + return String(buf); +} diff --git a/src/BLERemoteControlReceiver.h b/src/BLERemoteControlReceiver.h index f38b962..3ad7852 100644 --- a/src/BLERemoteControlReceiver.h +++ b/src/BLERemoteControlReceiver.h @@ -22,15 +22,15 @@ class BLERemoteControlReceiver : public BLERemoteControlBaseClass, public NimBLE BLERemoteControlReceiver(); ~BLERemoteControlReceiver(); - void begin(BLERemoteControlStorage* storage = nullptr); + void begin(BLERemoteControlStorage* storage, uint32_t pin); void on_command(ble_receive_callback_t callback); + void on_synchronize(ble_remote_sync_callback_t callback); - void start_synchronizing(); + void start_synchronizing(int seconds); void stop_synchronizing(); bool is_synchronizing(); - void on_synchronize(ble_remote_sync_callback_t callback); - void set_sync_pin(uint32_t pin); + void handle(); protected: void onResult(NimBLEAdvertisedDevice* advertised_device); @@ -41,13 +41,12 @@ class BLERemoteControlReceiver : public BLERemoteControlBaseClass, public NimBLE void process_service(NimBLEAdvertisedDevice* advertised_device); void synchronize_device(NimBLEAddress* address); + void check_sync_timeout(); uint32_t onPassKeyRequest(); BLERemoteControlStorage* get_storage(); - static void synchronize_task(void* vParams); - protected: NimBLEScan* ble_scan = nullptr; BLERemoteControlStorage* _storage; @@ -55,18 +54,19 @@ class BLERemoteControlReceiver : public BLERemoteControlBaseClass, public NimBLE ble_receive_callback_t receive_callback = nullptr; ble_remote_sync_callback_t sync_done_callback = nullptr; - bool _sync = false; - NimBLEAddress* sync_device_address; - uint32_t sync_pin = 123456; + uint32_t pin = 123456; + unsigned long sync_timestamp = 0; + unsigned long sync_timeout = 10000; }; BLERemoteControlReceiver::BLERemoteControlReceiver() {} BLERemoteControlReceiver::~BLERemoteControlReceiver() {} -void BLERemoteControlReceiver::begin(BLERemoteControlStorage* storage) { +void BLERemoteControlReceiver::begin(BLERemoteControlStorage* storage, uint32_t pin) { this->_storage = storage; + this->pin = pin; NimBLEDevice::setScanDuplicateCacheSize(10); NimBLEDevice::init(""); @@ -81,32 +81,43 @@ void BLERemoteControlReceiver::begin(BLERemoteControlStorage* storage) { ble_scan->setMaxResults(0); ble_scan->setDuplicateFilter(false); ble_scan->start(0, nullptr, false); - - xTaskCreate(synchronize_task, "sync", 2048, (void*)this, tskIDLE_PRIORITY + 1, nullptr); } void BLERemoteControlReceiver::on_command(ble_receive_callback_t callback) { receive_callback = callback; } -void BLERemoteControlReceiver::start_synchronizing() { _sync = true; }; +void BLERemoteControlReceiver::start_synchronizing(int seconds) { + sync_timestamp = millis(); + sync_timeout = ((unsigned long)seconds) * 1000; +}; -void BLERemoteControlReceiver::stop_synchronizing() { _sync = false; }; +void BLERemoteControlReceiver::stop_synchronizing() { + sync_timestamp = 0; +}; + +bool BLERemoteControlReceiver::is_synchronizing() { + unsigned long current_millis = millis(); + + bool _synchronize_timed_out = (sync_timestamp && sync_timeout && current_millis - sync_timestamp >= sync_timeout); + + if (_synchronize_timed_out) { + stop_synchronizing(); + if (sync_done_callback) sync_done_callback(nullptr); + } -bool BLERemoteControlReceiver::is_synchronizing() { return _sync; } + bool _is_synchronizing = (sync_timestamp > 0); + return _is_synchronizing; +} void BLERemoteControlReceiver::on_synchronize(ble_remote_sync_callback_t callback) { sync_done_callback = callback; } void BLERemoteControlReceiver::onResult(NimBLEAdvertisedDevice* advertised_device) { - BLERemoteControlStorage* storage = get_storage(); - if (advertised_device->haveManufacturerData()) { - if (storage != nullptr && storage->size() > 0) { - BLEManufacturerData manufacturer_data = advertised_device->getManufacturerData(); - if (manufacturer_data.company_id == 0xFFFF) process_manufacturer_data(&manufacturer_data); - } + BLEManufacturerData manufacturer_data = advertised_device->getManufacturerData(); + if (manufacturer_data.company_id == 0xFFFF) process_manufacturer_data(&manufacturer_data); } if (advertised_device->haveServiceUUID()) { @@ -114,22 +125,18 @@ void BLERemoteControlReceiver::onResult(NimBLEAdvertisedDevice* advertised_devic } }; -void BLERemoteControlReceiver::set_sync_pin(uint32_t pin) { - sync_pin = pin; -} - void BLERemoteControlReceiver::process_manufacturer_data(BLEManufacturerData* data) { BLERemoteControlStorage* storage = get_storage(); - auto remote_id = data->remote_id; - ble_remote_control_info_t* remote_control = storage->find(remote_id); - if (remote_control == nullptr) return; + auto remote_id = data->remote_id; + ble_remote_control_info_t remote_control; + if (storage->load(remote_id, &remote_control) == nullptr) return; BLERemoteControlMessage message; - decrypt_message(&message, data->encrypted_message, remote_control->aes_key); + decrypt_message(&message, data->encrypted_message, remote_control.aes_key); if (message.remote_id != remote_id) return; - process_command(&message, remote_control); + process_command(&message, &remote_control); } void BLERemoteControlReceiver::process_command(BLERemoteControlMessage* message, ble_remote_control_info_t* remote_control) { @@ -139,6 +146,7 @@ void BLERemoteControlReceiver::process_command(BLERemoteControlMessage* message, if (receive_callback) { ble_remote_command_info_t ci(command, remote_control); receive_callback(&ci); + get_storage()->save(remote_control); } } } @@ -161,8 +169,6 @@ void BLERemoteControlReceiver::process_service(NimBLEAdvertisedDevice* advertise if (advertised_device->isAdvertisingService(NimBLEUUID(remote_control_service_uuid))) { sync_device_address = new NimBLEAddress(advertised_device->getAddress()); } - - stop_synchronizing(); } void BLERemoteControlReceiver::synchronize_device(NimBLEAddress* address) { @@ -182,14 +188,8 @@ void BLERemoteControlReceiver::synchronize_device(NimBLEAddress* address) { if (pSecureCharacteristic != nullptr) { ble_remote_control_info_t remote_control = pSecureCharacteristic->readValue(); - - ble_remote_control_info_t* existing = storage->find(remote_control.id); - if (existing) { - existing->rolling_code = remote_control.rolling_code; - memcpy(existing->aes_key, remote_control.aes_key, sizeof(aes_key_t)); - } else { - storage->add(new ble_remote_control_info_t(remote_control), true); - } + storage->save(&remote_control); + if (sync_timeout) stop_synchronizing(); if (sync_done_callback) sync_done_callback(&remote_control); } @@ -200,7 +200,7 @@ void BLERemoteControlReceiver::synchronize_device(NimBLEAddress* address) { } uint32_t BLERemoteControlReceiver::onPassKeyRequest() { - return sync_pin; + return pin; } BLERemoteControlStorage* BLERemoteControlReceiver::get_storage() { @@ -208,15 +208,15 @@ BLERemoteControlStorage* BLERemoteControlReceiver::get_storage() { return _storage; } -void BLERemoteControlReceiver::synchronize_task(void* vParams) { - BLERemoteControlReceiver* instance = (BLERemoteControlReceiver*)vParams; +void BLERemoteControlReceiver::handle() { + check_sync_timeout(); - for (;;) { - if (instance->sync_device_address != nullptr) { - instance->synchronize_device(instance->sync_device_address); - delete instance->sync_device_address; - instance->sync_device_address = nullptr; - } - vTaskDelay(1); + if (is_synchronizing() && sync_device_address != nullptr) { + synchronize_device(sync_device_address); + delete sync_device_address; + sync_device_address = nullptr; } +} + +void BLERemoteControlReceiver::check_sync_timeout() { } \ No newline at end of file diff --git a/src/BLERemoteControlSender.h b/src/BLERemoteControlSender.h index 6548196..256b890 100644 --- a/src/BLERemoteControlSender.h +++ b/src/BLERemoteControlSender.h @@ -3,15 +3,28 @@ #include #include "BLERemoteControlBase.h" +#include "BLERemoteControlStorage.h" -class BLERemoteControlSender : public BLERemoteControlBaseClass { +class BLERemoteControlSender : public BLERemoteControlBaseClass, protected NimBLEServerCallbacks { public: - void begin(uint32_t pin = 123456); + void begin(uint32_t id, BLERemoteControlStorage* storage, uint32_t pin); - void send_command(uint32_t command, ble_remote_control_info_t* remote_control); - void start_sync(ble_remote_control_info_t& remote_control); + void send_command(uint32_t command); + + void start_synchronizing(int seconds); + void stop_synchronizing(); + bool is_synchronizing(); + + protected: + BLERemoteControlStorage* get_storage(); + virtual void onDisconnect(NimBLEServer* pServer) override; protected: + uint32_t id = 0x0001; + + int synchronize_timeout = 5; + unsigned long synchronizing_timestamp = 0; + NimBLEAdvertising* ble_advertising = nullptr; NimBLEAdvertisementData sync_adv_data; @@ -19,9 +32,11 @@ class BLERemoteControlSender : public BLERemoteControlBaseClass { NimBLEServer* ble_server = nullptr; NimBLEService* ble_service = nullptr; NimBLECharacteristic* ble_characteristic = nullptr; + + BLERemoteControlStorage* storage = nullptr; }; -void BLERemoteControlSender::begin(uint32_t pin) { +void BLERemoteControlSender::begin(uint32_t id, BLERemoteControlStorage* storage, uint32_t pin) { NimBLEDevice::init(""); NimBLEDevice::setPower(ESP_PWR_LVL_P9); @@ -29,16 +44,15 @@ void BLERemoteControlSender::begin(uint32_t pin) { NimBLEDevice::setSecurityPasskey(pin); NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); + this->id = id; + this->storage = storage; + ble_server = NimBLEDevice::createServer(); ble_server->advertiseOnDisconnect(false); + ble_server->setCallbacks(this); ble_service = ble_server->createService(NimBLEUUID(remote_control_service_uuid)); - ble_characteristic = ble_service->createCharacteristic( - NimBLEUUID(remote_control_characteristic_uuid), - NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::READ_ENC | - NIMBLE_PROPERTY::READ_AUTHEN - ); + ble_characteristic = ble_service->createCharacteristic(NimBLEUUID(remote_control_characteristic_uuid), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN); ble_service->start(); ble_advertising = NimBLEDevice::getAdvertising(); @@ -49,35 +63,76 @@ void BLERemoteControlSender::begin(uint32_t pin) { sync_adv_data.setCompleteServices(NimBLEUUID(remote_control_service_uuid)); } -void BLERemoteControlSender::start_sync(ble_remote_control_info_t& remote_control) { - ble_characteristic->setValue(remote_control); - remote_control.rolling_code++; +void BLERemoteControlSender::send_command(uint32_t command) { + ble_remote_control_info_t remote_control; + if (!get_storage()->load(id, &remote_control)) return; - ble_advertising->setAdvertisementType(BLE_GAP_CONN_MODE_UND); - ble_advertising->setAdvertisementData(sync_adv_data); - ble_advertising->start(5); -} + if (is_synchronizing()) stop_synchronizing(); -void BLERemoteControlSender::send_command(uint32_t command, ble_remote_control_info_t* remote_control) { BLEManufacturerData man_data; man_data.company_id = 0xFFFF; - man_data.remote_id = remote_control->id; + man_data.remote_id = remote_control.id; BLERemoteControlMessage message; - message.remote_id = remote_control->id; + message.remote_id = remote_control.id; message.command = command; - message.rolling_code = remote_control->rolling_code++; + message.rolling_code = remote_control.rolling_code++; message.nonce = random(0xFFFF); + get_storage()->save(&remote_control); - encrypt_message(man_data.encrypted_message, &message, remote_control->aes_key); + encrypt_message(man_data.encrypted_message, &message, remote_control.aes_key); NimBLEAdvertisementData adv_data; - + adv_data.setFlags(0x00); adv_data.setManufacturerData(std::string((const char*)&man_data, sizeof(BLEManufacturerData))); - + ble_advertising->setAdvertisementType(BLE_GAP_CONN_MODE_NON); ble_advertising->setAdvertisementData(adv_data); ble_advertising->start(1); +} + +void BLERemoteControlSender::start_synchronizing(int seconds) { + synchronize_timeout = (seconds * 1000); + + ble_remote_control_info_t remote_control; + if (!get_storage()->load(id, &remote_control)) return; + + ble_characteristic->setValue(remote_control); + remote_control.rolling_code++; + get_storage()->save(&remote_control); + + ble_advertising->setAdvertisementType(BLE_GAP_CONN_MODE_UND); + ble_advertising->setAdvertisementData(sync_adv_data); + ble_advertising->start(seconds); + synchronizing_timestamp = millis(); +} + +void BLERemoteControlSender::stop_synchronizing() { + ble_advertising->stop(); + synchronizing_timestamp = 0; +} + +bool BLERemoteControlSender::is_synchronizing() { + unsigned long current_millis = millis(); + + bool _synchronize_timed_out = (synchronizing_timestamp && synchronize_timeout && current_millis - synchronizing_timestamp >= synchronize_timeout); + if (_synchronize_timed_out) stop_synchronizing(); + + bool _is_synchronizing = (synchronizing_timestamp > 0); + return _is_synchronizing; +} + +BLERemoteControlStorage* BLERemoteControlSender::get_storage() { + if (storage == nullptr) storage = new BLERemoteControlStorage(); + return storage; +} + +void BLERemoteControlSender::onDisconnect(NimBLEServer* pServer) { + if (synchronize_timeout) { + if (is_synchronizing()) stop_synchronizing(); + } else { + start_synchronizing(0); + } } \ No newline at end of file diff --git a/src/BLERemoteControlStorage.h b/src/BLERemoteControlStorage.h index 8564fe3..542b56e 100644 --- a/src/BLERemoteControlStorage.h +++ b/src/BLERemoteControlStorage.h @@ -6,91 +6,10 @@ #include "BLERemoteControlInfo.h" -struct ble_remote_control_storage_info_t { - ble_remote_control_info_t* remote_control; - - bool delete_on_remove = false; -}; - class BLERemoteControlStorage { public: - BLERemoteControlStorage(); - virtual ~BLERemoteControlStorage(); - - void add(ble_remote_control_info_t* remote_control, bool delete_on_remove = false); - void add(ble_remote_control_info_t& remote_control); - - void remove(ble_remote_control_info_t* remote_control); - void forEach(std::function callback); - ble_remote_control_info_t* operator[](size_t index); - - size_t size(); - ble_remote_control_info_t* find(uint16_t id); - - protected: - ble_remote_control_storage_info_t* find(ble_remote_control_info_t* remote_control); - - protected: - std::vector remote_controls; + virtual void save(const ble_remote_control_info_t* remote_control){}; + virtual ble_remote_control_info_t* load(uint16_t id, ble_remote_control_info_t* remote_control) { return nullptr; }; + virtual bool exist(uint16_t id) { return false; } + virtual void remove(uint16_t id) {} }; - -BLERemoteControlStorage::BLERemoteControlStorage() {} - -BLERemoteControlStorage::~BLERemoteControlStorage() { - for (auto element : remote_controls) { - if (element->delete_on_remove) delete element->remote_control; - delete element; - } - remote_controls.clear(); -} - -void BLERemoteControlStorage::add(ble_remote_control_info_t* remote_control, bool delete_on_remove) { - ble_remote_control_storage_info_t* storage_info = new ble_remote_control_storage_info_t; - - storage_info->delete_on_remove = delete_on_remove; - storage_info->remote_control = remote_control; - - remote_controls.push_back(storage_info); -} - -void BLERemoteControlStorage::add(ble_remote_control_info_t& remote_control) { - add(&remote_control, false); -} - -void BLERemoteControlStorage::remove(ble_remote_control_info_t* remote_control) { - if (remote_control == nullptr) return; - ble_remote_control_storage_info_t* storage_info = find(remote_control); - if (storage_info == nullptr) return; - if (storage_info->delete_on_remove) delete storage_info->remote_control; - remote_controls.erase(std::remove(remote_controls.begin(), remote_controls.end(), storage_info), remote_controls.end()); - delete storage_info; -} - -void BLERemoteControlStorage::forEach(std::function callback) { - if (callback == nullptr) return; - for (auto& storage_info : remote_controls) { - callback(storage_info->remote_control); - } -} - -ble_remote_control_info_t* BLERemoteControlStorage::find(uint16_t id) { - for (auto storage_info : remote_controls) { - if (storage_info->remote_control->id == id) return storage_info->remote_control; - } - return nullptr; -} - -size_t BLERemoteControlStorage::size() { - return remote_controls.size(); -} - -ble_remote_control_storage_info_t* BLERemoteControlStorage::find(ble_remote_control_info_t* remote_control) { - for (auto& element : remote_controls) { - if (element->remote_control == remote_control) return element; - } - return nullptr; -} - -ble_remote_control_info_t* BLERemoteControlStorage::operator[](size_t index) { - return remote_controls[index]->remote_control; -} \ No newline at end of file diff --git a/src/NVSRemoteControlStorage.h b/src/NVSRemoteControlStorage.h index a93f260..ae09bc5 100644 --- a/src/NVSRemoteControlStorage.h +++ b/src/NVSRemoteControlStorage.h @@ -4,47 +4,63 @@ #include "BLERemoteControlStorage.h" -const char* storage_key_name_size = "size"; - -class NVSRemoteControlStorage : public BLERemoteControlStorage, protected Preferences { +class NVSRemoteControlStorage : public BLERemoteControlStorage { public: - using Preferences::begin; - using Preferences::clear; - using Preferences::end; + void begin(const char* name, const char* partition_label = nullptr); + void clear(); + void end(); + + void save(const ble_remote_control_info_t* remote_control) override; + ble_remote_control_info_t* load(uint16_t id, ble_remote_control_info_t* remote_control) override; + bool exist(uint16_t id) override; + void remove(uint16_t id) override; - bool load(); - void save(); + protected: + typedef char nvs_key_t[5]; + const char* make_key(const uint16_t id, nvs_key_t key); - void remove(ble_remote_control_info_t* remote_control); + protected: + Preferences preferences; }; -bool NVSRemoteControlStorage::load() { - uint16_t size = getUShort(storage_key_name_size, 0); - if (size == 0) return false; +void NVSRemoteControlStorage::begin(const char* name, const char* partition_label) { + preferences.begin(name, false, partition_label); +} + +void NVSRemoteControlStorage::clear() { + preferences.clear(); +} - for (size_t i = 0; i < size; i++) { - ble_remote_control_info_t* rc = new ble_remote_control_info_t(i, false); - char key[5]; - sprintf(key, "%4x", i); - getBytes((const char*)key, rc, sizeof(ble_remote_control_info_t)); - add(rc, true); - } +void NVSRemoteControlStorage::end() { + preferences.end(); +} - return true; +void NVSRemoteControlStorage::save(const ble_remote_control_info_t* remote_control) { + nvs_key_t key; + preferences.putBytes(make_key(remote_control->id, key), remote_control, sizeof(ble_remote_control_info_t)); } -void NVSRemoteControlStorage::save() { - putUShort(storage_key_name_size, remote_controls.size()); +ble_remote_control_info_t* NVSRemoteControlStorage::load(uint16_t id, ble_remote_control_info_t* remote_control) { + nvs_key_t key; + if (!exist(id)) return nullptr; + + size_t size = preferences.getBytes(make_key(id, key), remote_control, sizeof(ble_remote_control_info_t)); + if (size == 0) return nullptr; + + return remote_control; +} + +bool NVSRemoteControlStorage::exist(uint16_t id) { + nvs_key_t key; + return preferences.isKey(make_key(id, key)); +} - for (size_t i = 0; i < remote_controls.size(); i++) { - char key[5]; - sprintf(key, "%4x", i); - putBytes((const char*)key, remote_controls[i]->remote_control, sizeof(ble_remote_control_info_t)); - } +void NVSRemoteControlStorage::remove(uint16_t id) { + nvs_key_t key; + preferences.remove(make_key(id, key)); } -void NVSRemoteControlStorage::remove(ble_remote_control_info_t* remote_control) { - BLERemoteControlStorage::remove(remote_control); - Preferences::clear(); - save(); +const char* NVSRemoteControlStorage::make_key(const uint16_t id, nvs_key_t key) { + snprintf(key, sizeof(nvs_key_t), "%04x", id); + return key; } \ No newline at end of file From e33967c20b95c52d58a6a91f5e7392dca16fe1c1 Mon Sep 17 00:00:00 2001 From: sivar2311 Date: Sun, 27 Mar 2022 12:31:10 +0200 Subject: [PATCH 2/2] Fixed: Sender example for Version 1.0.0 --- examples/Sender/Sender.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/Sender/Sender.ino b/examples/Sender/Sender.ino index 935e7fb..d00301f 100644 --- a/examples/Sender/Sender.ino +++ b/examples/Sender/Sender.ino @@ -43,8 +43,7 @@ void setup_storage() { storage.begin("ble_remote"); if (storage.exist(UNIQUE_REMOTE_ID) == false) { - storage.add(new ble_remote_control_info_t(UNIQUE_REMOTE_ID, true)); - storage.save(); + storage.save(new ble_remote_control_info_t(UNIQUE_REMOTE_ID, true)); } }