// This is a personal academic project. Dear PVS-Studio, please check it. // PVS-Studio Static Code Analyzer for C, C++, C#, and Java: https://pvs-studio.com #include "BluetoothDispatcher.hpp" static DeviceConnectedCb deviceConnectedCallback = nullptr; static void deviceConnectedStaticCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param); BluetoothDispatcher::BluetoothDispatcher(BluetoothSerial *controller, const char *device_name) { assert(controller != nullptr); assert(device_name != nullptr); _device_name = device_name; _controller = controller; } bool BluetoothDispatcher::initialize(volatile bool loop_on_fail, int readTimeoutMS) { _controller->enableSSP(); _controller->onConfirmRequest([this](uint16_t pin) { _onConfirmRequest(pin); }); _controller->onAuthComplete([this](boolean success) { _onAuthComplete(success); }); _controller->register_callback(deviceConnectedStaticCallback); deviceConnectedCallback = [this](BTAddress device) { _onDeviceConnected(device); }; _controller->setTimeout(2); bool success = _controller->begin(_device_name, false); if (!success) { ESP_LOGI(_tag, "Failed to initialize Bluetooth controller!"); while (loop_on_fail) ; return false; } else { ESP_LOGI(_tag, "Bluetooth host initialized"); return true; } } void BluetoothDispatcher::onNewPackageReceived(NewPackageCallback newPackageReceivedCb) { _newPackageReceivedCb = newPackageReceivedCb; } void BluetoothDispatcher::tick() { /* Call the callback, if new package received */ while (_controller->available() and _buffer.length() <= _buffer_size) { _buffer += (char)_controller->read(); } if (_buffer.endsWith("\n\r")) { char buffer[_buffer_size]; _buffer.substring(0, _buffer.lastIndexOf('}'), buffer); ESP_LOGD(_tag, "Received new buffer %s", buffer); if (_newPackageReceivedCb) { _newPackageReceivedCb(buffer); } _buffer.clear(); } if (_buffer.length() > _available_buffer_size) { _buffer.clear(); } } BluetoothDispatcher::~BluetoothDispatcher() { _controller->end(); delete _controller; } void BluetoothDispatcher::_onConfirmRequest(uint16_t pin) { ESP_LOGI(_tag, "The Bluetooth PIN is: %06lu", (long unsigned int)pin); _controller->confirmReply(true); } void BluetoothDispatcher::_onAuthComplete(boolean success) const { if (success) { ESP_LOGI(_tag, "Pairing success!"); } else { ESP_LOGI(_tag, "Pairing failed, rejected by user!"); } } void BluetoothDispatcher::_onDeviceConnected(BTAddress device) const { ESP_LOGI(_tag, "New device connected: %s", device.toString(true).c_str()); if (_deviceConnectedCallback) { _deviceConnectedCallback(device); } } void BluetoothDispatcher::onNewDeviceConnected(DeviceConnectedCb deviceConnectedCb) { /* Callback called if device connected successfully. */ _deviceConnectedCallback = deviceConnectedCb; } void BluetoothDispatcher::sendPackage(const char *package, size_t size) { _controller->write((uint8_t *)package, size); } static void deviceConnectedStaticCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { if (event == ESP_SPP_SRV_OPEN_EVT and param->srv_open.status == ESP_SPP_SUCCESS and deviceConnectedCallback) { deviceConnectedCallback(BTAddress(param->srv_open.rem_bda)); } }