-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
BLE NUS - text console over BLE #560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
ff7c2fa
Echo example working
hubmartin 5620ab8
WIP: Save conn handle, add print
hubmartin 1a5de5e
Trying to add Console class
hubmartin ae4b46a
Move Console to Components
hubmartin bc0f7c1
Working console.Print concept
hubmartin 2a0754b
WIP
hubmartin 8d12806
RX callback registration
hubmartin 7ebe928
Add VSCode ST-link debug config
hubmartin 0fa1587
Merge branch 'bootloop' into ble-nus
hubmartin 8c95f55
First commands working
hubmartin 18c0f46
Move console processing to SystemTask
hubmartin 774e2f8
Add MotionController debug output
hubmartin 6f84ecd
Merge branch 'develop' into ble-nus
hubmartin e560bc9
Cleanup
hubmartin 7191bb5
Add rxPos len check
hubmartin 6ec3aa4
Cleanup
hubmartin 0170cfe
Add hatmajster suggestions
hubmartin eeda7ad
Clean commented NRF log block
hubmartin f15ce01
Move acc debug cmd & lvgl info to funtions
hubmartin a3317d8
Compare with \r & \n
hubmartin e94d0fd
Handle console by event Messages::ConsoleProcess
hubmartin b1304e9
Comment LVGL commands because of recovery FW does not compiled
hubmartin e019aa0
Merge branch 'develop' into ble-nus
hubmartin 1dcbeac
Merge branch 'develop' into ble-nus
hubmartin 0de7822
Update vibrations to RunForDuration
hubmartin dcc4a6e
Merge branch 'develop' into ble-nus
hubmartin 2ad36ad
Clean code, lower rx buffer
hubmartin f667aab
Remove console.Print examples
hubmartin 7f18a01
Merge branch 'develop' into ble-nus
hubmartin 16736d5
clang-format
hubmartin 94215c7
Run clang-tidy
hubmartin 946867e
Merge branch 'develop' into ble-nus
hubmartin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,6 +59,5 @@ | |
| "target/nrf52.cfg" | ||
| ], | ||
| } | ||
|
|
||
| ] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| #include "BleNus.h" | ||
| #include "components/console/Console.h" | ||
|
|
||
| using namespace Pinetime::Controllers; | ||
|
|
||
| constexpr ble_uuid128_t BleNus::nusServiceUuid; | ||
| constexpr ble_uuid128_t BleNus::rxCharacteristicUuid; | ||
| constexpr ble_uuid128_t BleNus::txCharacteristicUuid; | ||
| uint16_t BleNus::attributeReadHandle; | ||
|
|
||
| int BleNusCallback(uint16_t connectionHandle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { | ||
| auto *deviceInformationService = static_cast<BleNus*>(arg); | ||
| return deviceInformationService->OnDeviceInfoRequested(connectionHandle, attr_handle, ctxt); | ||
| } | ||
|
|
||
| void BleNus::Init() { | ||
| int res = 0; | ||
| res = ble_gatts_count_cfg(serviceDefinition); | ||
| ASSERT(res == 0); | ||
|
|
||
| res = ble_gatts_add_svcs(serviceDefinition); | ||
| ASSERT(res == 0); | ||
| } | ||
|
|
||
| void BleNus::SetConnectionHandle(uint16_t connection_handle) { | ||
| connectionHandle = connection_handle; | ||
| } | ||
|
|
||
| void BleNus::Print(const std::string str) { | ||
| os_mbuf* om; | ||
| om = ble_hs_mbuf_from_flat(str.c_str(), str.length()); | ||
|
|
||
| if (om) { | ||
| ble_gattc_notify_custom(connectionHandle, attributeReadHandle, om); | ||
| } | ||
| } | ||
|
|
||
| void BleNus::RegisterRxCallback(std::function<void(char*, int)> f) { | ||
| this->rxDataFunction = f; | ||
| } | ||
|
|
||
| int BleNus::OnDeviceInfoRequested(uint16_t connectionHandle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) { | ||
| (void) connectionHandle; | ||
| (void) attr_handle; | ||
|
|
||
| os_mbuf* om = ctxt->om; | ||
|
|
||
| switch (ctxt->op) { | ||
| case BLE_GATT_ACCESS_OP_WRITE_CHR: | ||
| while (om) { | ||
|
|
||
| // Test BLE console it with Bluefruit, NRF Toolbox (you must add enter before hitting send! | ||
| // https://devzone.nordicsemi.com/f/nordic-q-a/33687/nrf-toolbox-2-6-0-uart-does-not-send-lf-cr-or-cr-lf-as-eol) on the phone, or in | ||
| // any Chromium-based web browser https://terminal.hardwario.com/ | ||
|
|
||
| rxDataFunction((char*) om->om_data, (int) om->om_len); | ||
|
|
||
| om = SLIST_NEXT(om, om_next); | ||
| } | ||
| return 0; | ||
| default: | ||
| assert(0); | ||
| return BLE_ATT_ERR_UNLIKELY; | ||
| } | ||
| } | ||
|
|
||
| BleNus::BleNus() | ||
| : characteristicDefinition {{ | ||
| .uuid = &rxCharacteristicUuid.u, | ||
| .access_cb = BleNusCallback, | ||
| .arg = this, | ||
| .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP, | ||
| }, | ||
| {.uuid = &txCharacteristicUuid.u, | ||
| .access_cb = BleNusCallback, | ||
| .arg = this, | ||
| .flags = BLE_GATT_CHR_F_NOTIFY, | ||
| .val_handle = &attributeReadHandle}, | ||
| {0}}, | ||
| serviceDefinition { | ||
| {/* Device Information Service */ | ||
| .type = BLE_GATT_SVC_TYPE_PRIMARY, | ||
| .uuid = &nusServiceUuid.u, | ||
| .characteristics = characteristicDefinition}, | ||
| {0}, | ||
| } { | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #pragma once | ||
| #define min // workaround: nimble's min/max macros conflict with libstdc++ | ||
hubmartin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #define max | ||
| #include <host/ble_gap.h> | ||
| #undef max | ||
| #undef min | ||
| #include "Version.h" | ||
| #include <functional> | ||
|
|
||
| namespace Pinetime { | ||
| namespace Components { | ||
| class Console; | ||
| } | ||
| namespace Controllers { | ||
| class BleNus { | ||
| public: | ||
| BleNus(); | ||
| void Init(); | ||
| void SetConnectionHandle(uint16_t connection_handle); | ||
| void Print(const std::string str); | ||
|
|
||
| void RegisterRxCallback(std::function<void(char*, int)> f); | ||
|
|
||
| int OnDeviceInfoRequested(uint16_t connectionHandle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt); | ||
|
|
||
| private: | ||
| static uint16_t attributeReadHandle; | ||
| uint16_t connectionHandle; | ||
|
|
||
| std::function<void(char*, int)> rxDataFunction; | ||
|
|
||
| // 6E400001-B5A3-F393-E0A9-E50E24DCCA9E | ||
| static constexpr ble_uuid128_t nusServiceUuid { | ||
| .u {.type = BLE_UUID_TYPE_128}, | ||
| .value = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e}}; | ||
| // 6E400002-B5A3-F393-E0A9-E50E24DCCA9E | ||
| static constexpr ble_uuid128_t rxCharacteristicUuid { | ||
| .u {.type = BLE_UUID_TYPE_128}, | ||
| .value = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e}}; | ||
| // 6E400003-B5A3-F393-E0A9-E50E24DCCA9E | ||
| static constexpr ble_uuid128_t txCharacteristicUuid { | ||
| .u {.type = BLE_UUID_TYPE_128}, | ||
| .value = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e}}; | ||
|
|
||
| struct ble_gatt_chr_def characteristicDefinition[3]; | ||
| struct ble_gatt_svc_def serviceDefinition[2]; | ||
| }; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| #include "Console.h" | ||
| #include "components/ble/BleNus.h" | ||
| #include "components/ble/NimbleController.h" | ||
| #include "systemtask/SystemTask.h" | ||
|
|
||
| using namespace Pinetime::Components; | ||
|
|
||
| Console::Console(Pinetime::System::SystemTask& systemTask, | ||
| Pinetime::Controllers::NimbleController& nimbleController, | ||
| Pinetime::Controllers::FS& fs, | ||
| Pinetime::Components::LittleVgl& lvgl, | ||
| Pinetime::Controllers::MotorController& motorController, | ||
| Pinetime::Drivers::Cst816S& touchPanel, | ||
| Pinetime::Drivers::SpiNorFlash& spiNorFlash, | ||
| Pinetime::Drivers::TwiMaster& twiMaster, | ||
| Pinetime::Controllers::MotionController& motionController) | ||
| : systemTask {systemTask}, | ||
| nimbleController {nimbleController}, | ||
| fs {fs}, | ||
| lvgl {lvgl}, | ||
| motorController {motorController}, | ||
| touchPanel {touchPanel}, | ||
| spiNorFlash {spiNorFlash}, | ||
| twiMaster {twiMaster}, | ||
| motionController {motionController} { | ||
| } | ||
|
|
||
| void Console::Init() { | ||
| auto rxCallback = [this](char* str, int length) { | ||
| this->Received(str, length); | ||
| }; | ||
|
|
||
| nimbleController.bleNus().RegisterRxCallback(rxCallback); | ||
| } | ||
|
|
||
| void Console::Print(const std::string str) { | ||
| nimbleController.bleNus().Print(str); | ||
| } | ||
|
|
||
| static bool cmdCmp(char* buffer, const std::string search) { | ||
| return strncmp(buffer, search.c_str(), search.length()) == 0; | ||
| } | ||
|
|
||
| void Console::Process() { | ||
| static constexpr int maxArgumentsCount = 4; | ||
| static constexpr int maxBufferLength = 64; | ||
|
|
||
| char arg_buffer[maxBufferLength]; | ||
| const char* args[maxArgumentsCount]; | ||
|
|
||
| // Copy string, becase we replace ' ' with '\0' for proper string termination | ||
| strncpy(arg_buffer, rxBuffer, sizeof(arg_buffer)); | ||
|
|
||
| // First argument is always command name itself | ||
| uint16_t argc = 1; | ||
| args[0] = arg_buffer; | ||
|
|
||
| uint16_t param_len = strlen(rxBuffer); | ||
|
|
||
| for (uint16_t i = 0; i < param_len; i++) { | ||
hubmartin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (rxBuffer[i] == ' ' && param_len > (i + 1)) { | ||
| arg_buffer[i] = '\0'; | ||
| args[argc++] = &arg_buffer[i + 1]; | ||
| } | ||
|
|
||
| if (argc == maxArgumentsCount) { | ||
| // Max argument count reached | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| (void) args; | ||
| (void) argc; | ||
|
|
||
| // Simple stupid command comparison, later would be nice to add commands lookup table with argument parsing | ||
| if (cmdCmp(rxBuffer, "VIBRATE")) { | ||
| motorController.RunForDuration(100); | ||
| } else if (cmdCmp(rxBuffer, "WKUP")) { | ||
| systemTask.PushMessage(Pinetime::System::Messages::GoToRunning); | ||
| } else if (cmdCmp(rxBuffer, "SLEEP")) { | ||
| systemTask.PushMessage(Pinetime::System::Messages::GoToSleep); | ||
| } | ||
| } | ||
|
|
||
| void Console::Received(char* str, int length) { | ||
| for (int i = 0; i < length; i++) { | ||
| // Wrap if input is too long without CR/LN | ||
| if (rxPos == bufferSize - 1) { | ||
| rxPos = 0; | ||
| } | ||
|
|
||
| rxBuffer[rxPos++] = str[i]; | ||
| rxBuffer[rxPos] = '\0'; // terminate for debug print | ||
|
|
||
| if (str[i] == '\n' || str[i] == '\r') { | ||
| rxPos = 0; | ||
| systemTask.PushMessage(System::Messages::ConsoleProcess); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.