466 lines
14 KiB
C++
466 lines
14 KiB
C++
|
/*
|
||
|
; Project: Open Vehicle Monitor System
|
||
|
; Date: 14th March 2017
|
||
|
;
|
||
|
; Changes:
|
||
|
; 1.0 Initial release
|
||
|
;
|
||
|
; (C) 2011 Michael Stegen / Stegen Electronics
|
||
|
; (C) 2011-2017 Mark Webb-Johnson
|
||
|
; (C) 2011 Sonny Chen @ EPRO/DX
|
||
|
;
|
||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
; of this software and associated documentation files (the "Software"), to deal
|
||
|
; in the Software without restriction, including without limitation the rights
|
||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
; copies of the Software, and to permit persons to whom the Software is
|
||
|
; furnished to do so, subject to the following conditions:
|
||
|
;
|
||
|
; The above copyright notice and this permission notice shall be included in
|
||
|
; all copies or substantial portions of the Software.
|
||
|
;
|
||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
; THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include <string.h>
|
||
|
#include "esp_system.h"
|
||
|
#include "esp32bluetooth_gap.h"
|
||
|
#include "esp32bluetooth_gatts.h"
|
||
|
#include "ovms_config.h"
|
||
|
#include "ovms_events.h"
|
||
|
|
||
|
#include "ovms_log.h"
|
||
|
static const char *TAG = "bt-gatts";
|
||
|
|
||
|
esp32bluetoothGATTS MyBluetoothGATTS __attribute__ ((init_priority (8012)));
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// esp32bluetoothCharacteristic
|
||
|
|
||
|
esp32bluetoothCharacteristic::esp32bluetoothCharacteristic(
|
||
|
esp32bluetoothApp* app,
|
||
|
esp_bt_uuid_t* charuuid,
|
||
|
esp_bt_uuid_t* descruuid = NULL)
|
||
|
{
|
||
|
m_app = app;
|
||
|
m_notifying = false;
|
||
|
m_indicating = false;
|
||
|
|
||
|
memcpy(&m_char_uuid,charuuid,sizeof(esp_bt_uuid_t));
|
||
|
m_char_handle = 0;
|
||
|
m_char_perm = 0;
|
||
|
m_char_property = 0;
|
||
|
|
||
|
if (descruuid != NULL)
|
||
|
{
|
||
|
memcpy(&m_descr_uuid,&descruuid,sizeof(esp_bt_uuid_t));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memset(&m_descr_uuid,0,sizeof(esp_bt_uuid_t));
|
||
|
}
|
||
|
m_descr_handle = 0;
|
||
|
}
|
||
|
|
||
|
esp32bluetoothCharacteristic::~esp32bluetoothCharacteristic()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// esp32bluetoothApp
|
||
|
|
||
|
esp32bluetoothApp::esp32bluetoothApp(const char* name)
|
||
|
{
|
||
|
m_name = name;
|
||
|
m_gatts_if = ESP_GATT_IF_NONE;
|
||
|
m_app_id = 0;
|
||
|
m_conn_id = 0;
|
||
|
m_service_handle = 0;
|
||
|
memset(&m_service_id, 0, sizeof(m_service_id));
|
||
|
m_mtu = 0;
|
||
|
}
|
||
|
|
||
|
esp32bluetoothApp::~esp32bluetoothApp()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventRegistered(esp_ble_gatts_cb_param_t::gatts_reg_evt_param *reg)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventRead(esp_ble_gatts_cb_param_t::gatts_read_evt_param *read)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventWrite(esp_ble_gatts_cb_param_t::gatts_write_evt_param *write)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventExecWrite(esp_ble_gatts_cb_param_t::gatts_exec_write_evt_param *execwrite)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventMTU(esp_ble_gatts_cb_param_t::gatts_mtu_evt_param *mtu)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventConf(esp_ble_gatts_cb_param_t::gatts_conf_evt_param *conf)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventUnregistered()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventDelete(esp_ble_gatts_cb_param_t::gatts_delete_evt_param *del)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventStart(esp_ble_gatts_cb_param_t::gatts_start_evt_param *start)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventStop(esp_ble_gatts_cb_param_t::gatts_stop_evt_param *stop)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventConnect(esp_ble_gatts_cb_param_t::gatts_connect_evt_param *connect)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventDisconnect(esp_ble_gatts_cb_param_t::gatts_disconnect_evt_param *disconnect)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventOpen(esp_ble_gatts_cb_param_t::gatts_open_evt_param *open)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventCancelOpen(esp_ble_gatts_cb_param_t::gatts_cancel_open_evt_param *cancelopen)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventClose(esp_ble_gatts_cb_param_t::gatts_close_evt_param *close)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventListen()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventCongest(esp_ble_gatts_cb_param_t::gatts_congest_evt_param *congest)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventCreate(esp_ble_gatts_cb_param_t::gatts_add_attr_tab_evt_param *attrtab)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventAddChar(esp_ble_gatts_cb_param_t::gatts_add_char_evt_param *addchar)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothApp::EventAddCharDescr(esp_ble_gatts_cb_param_t::gatts_add_char_descr_evt_param *adddescr)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// esp32bluetoothGATTS
|
||
|
|
||
|
void ble_gatts_event_handler(esp_gatts_cb_event_t event,
|
||
|
esp_gatt_if_t gatts_if,
|
||
|
esp_ble_gatts_cb_param_t *param)
|
||
|
{
|
||
|
MyBluetoothGATTS.EventHandler(event, gatts_if, param);
|
||
|
}
|
||
|
|
||
|
esp32bluetoothGATTS::esp32bluetoothGATTS()
|
||
|
{
|
||
|
ESP_LOGI(TAG, "Initialising Bluetooth GATTS (8012)");
|
||
|
}
|
||
|
|
||
|
esp32bluetoothGATTS::~esp32bluetoothGATTS()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothGATTS::RegisterForEvents()
|
||
|
{
|
||
|
esp_err_t ret = esp_ble_gatts_register_callback(ble_gatts_event_handler);
|
||
|
if (ret)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "gatts register error, error code = %x", ret);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothGATTS::EventHandler(esp_gatts_cb_event_t event,
|
||
|
esp_gatt_if_t gatts_if,
|
||
|
esp_ble_gatts_cb_param_t *param)
|
||
|
{
|
||
|
for (esp32bluetoothApp* app : m_apps)
|
||
|
{
|
||
|
if (event == ESP_GATTS_REG_EVT)
|
||
|
{
|
||
|
// Store the gatts_if for the registered app
|
||
|
if (param->reg.app_id == app->m_app_id)
|
||
|
{
|
||
|
if (param->reg.status == ESP_GATT_OK)
|
||
|
{
|
||
|
ESP_LOGI(TAG,"ESP_GATTS_REG_EVT register app %s (0x%04x) ok with interface ID %d",
|
||
|
app->m_name, param->reg.app_id, gatts_if);
|
||
|
app->m_gatts_if = gatts_if;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGE(TAG, "ESP_GATTS_REG_EVT register app %s (0x%04x) failed with status %d",
|
||
|
app->m_name,
|
||
|
param->reg.app_id,
|
||
|
param->reg.status);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ((gatts_if == ESP_GATT_IF_NONE) ||
|
||
|
(gatts_if == app->m_gatts_if))
|
||
|
{
|
||
|
switch (event)
|
||
|
{
|
||
|
case ESP_GATTS_REG_EVT:
|
||
|
{
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_REG_EVT/%s",app->m_name);
|
||
|
|
||
|
std::string devname = MyConfig.GetParamValue("vehicle", "id");
|
||
|
if (devname.empty())
|
||
|
{
|
||
|
devname = std::string("OVMS");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
devname.insert(0,"OVMS ");
|
||
|
}
|
||
|
esp_ble_gap_set_device_name(devname.c_str());
|
||
|
esp_ble_gap_config_local_privacy(true);
|
||
|
|
||
|
app->EventRegistered(¶m->reg);
|
||
|
break;
|
||
|
}
|
||
|
case ESP_GATTS_READ_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_READ_EVT/%s conn_id %d, trans_id %d, handle %d",
|
||
|
app->m_name,
|
||
|
param->read.conn_id, param->read.trans_id, param->read.handle);
|
||
|
app->EventRead(¶m->read);
|
||
|
break;
|
||
|
case ESP_GATTS_WRITE_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_WRITE_EVT/%s conn_id %d, trans_id %d, handle %d, write %d bytes, value:",
|
||
|
app->m_name,
|
||
|
param->write.conn_id, param->write.trans_id, param->write.handle,
|
||
|
param->write.len);
|
||
|
esp_log_buffer_hex(TAG, param->write.value, param->write.len);
|
||
|
app->EventWrite(¶m->write);
|
||
|
break;
|
||
|
case ESP_GATTS_EXEC_WRITE_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_EXEC_WRITE_EVT/%s conn_id %d, trans_id %d",
|
||
|
app->m_name,
|
||
|
param->exec_write.conn_id, param->exec_write.trans_id);
|
||
|
app->EventExecWrite(¶m->exec_write);
|
||
|
break;
|
||
|
case ESP_GATTS_MTU_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_MTU_EVT/%s conn_id %d, mtu %d",
|
||
|
app->m_name,
|
||
|
param->mtu.conn_id,
|
||
|
param->mtu.mtu);
|
||
|
app->m_mtu = param->mtu.mtu;
|
||
|
app->EventMTU(¶m->mtu);
|
||
|
break;
|
||
|
case ESP_GATTS_CONF_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_CONF_EVT/%s",app->m_name);
|
||
|
app->EventConf(¶m->conf);
|
||
|
break;
|
||
|
case ESP_GATTS_UNREG_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_UNREG_EVT/%s",app->m_name);
|
||
|
app->EventUnregistered();
|
||
|
break;
|
||
|
case ESP_GATTS_DELETE_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_DELETE_EVT/%s",app->m_name);
|
||
|
app->EventDelete(¶m->del);
|
||
|
break;
|
||
|
case ESP_GATTS_START_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_START_EVT/%s",app->m_name);
|
||
|
app->EventStart(¶m->start);
|
||
|
break;
|
||
|
case ESP_GATTS_STOP_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_STOP_EVT/%s",app->m_name);
|
||
|
app->EventStop(¶m->stop);
|
||
|
break;
|
||
|
case ESP_GATTS_CONNECT_EVT:
|
||
|
{
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_CONNECT_EVT/%s conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x",
|
||
|
app->m_name,
|
||
|
param->connect.conn_id,
|
||
|
param->connect.remote_bda[0],
|
||
|
param->connect.remote_bda[1],
|
||
|
param->connect.remote_bda[2],
|
||
|
param->connect.remote_bda[3],
|
||
|
param->connect.remote_bda[4],
|
||
|
param->connect.remote_bda[5]);
|
||
|
|
||
|
app->EventConnect(¶m->connect);
|
||
|
|
||
|
char signal[32];
|
||
|
sprintf(signal,"bt.connect.%02x:%02x:%02x:%02x:%02x:%02x",
|
||
|
param->connect.remote_bda[0],
|
||
|
param->connect.remote_bda[1],
|
||
|
param->connect.remote_bda[2],
|
||
|
param->connect.remote_bda[3],
|
||
|
param->connect.remote_bda[4],
|
||
|
param->connect.remote_bda[5]);
|
||
|
MyEvents.SignalEvent(signal, NULL);
|
||
|
|
||
|
app->m_conn_id = param->connect.conn_id;
|
||
|
|
||
|
if (app->m_app_slot == 0)
|
||
|
{
|
||
|
esp_ble_conn_update_params_t conn_params;
|
||
|
memset(&conn_params,0,sizeof(conn_params));
|
||
|
memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
|
||
|
|
||
|
/* For the IOS system, please reference the apple official documents about the ble connection parameters restrictions. */
|
||
|
conn_params.latency = 0;
|
||
|
conn_params.max_int = 0x30; // max_int = 0x30*1.25ms = 40ms
|
||
|
conn_params.min_int = 0x10; // min_int = 0x10*1.25ms = 20ms
|
||
|
conn_params.timeout = 400; // timeout = 400*10ms = 4000ms
|
||
|
|
||
|
//start sent the update connection parameters to the peer device.
|
||
|
esp_ble_gap_update_conn_params(&conn_params);
|
||
|
esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_MITM);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case ESP_GATTS_DISCONNECT_EVT:
|
||
|
{
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_DISCONNECT_EVT/%s conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x",
|
||
|
app->m_name,
|
||
|
param->disconnect.conn_id,
|
||
|
param->disconnect.remote_bda[0],
|
||
|
param->disconnect.remote_bda[1],
|
||
|
param->disconnect.remote_bda[2],
|
||
|
param->disconnect.remote_bda[3],
|
||
|
param->disconnect.remote_bda[4],
|
||
|
param->disconnect.remote_bda[5]);
|
||
|
|
||
|
app->EventDisconnect(¶m->disconnect);
|
||
|
|
||
|
char signal[32];
|
||
|
sprintf(signal,"bt.disconnect.%02x:%02x:%02x:%02x:%02x:%02x",
|
||
|
param->disconnect.remote_bda[0],
|
||
|
param->disconnect.remote_bda[1],
|
||
|
param->disconnect.remote_bda[2],
|
||
|
param->disconnect.remote_bda[3],
|
||
|
param->disconnect.remote_bda[4],
|
||
|
param->disconnect.remote_bda[5]);
|
||
|
MyEvents.SignalEvent(signal, NULL);
|
||
|
|
||
|
if (app->m_app_slot == 0)
|
||
|
{
|
||
|
MyBluetoothGAP.StartAdvertising();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case ESP_GATTS_OPEN_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_OPEN_EVT/%s",app->m_name);
|
||
|
app->EventOpen(¶m->open);
|
||
|
break;
|
||
|
case ESP_GATTS_CANCEL_OPEN_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_CANCEL_OPEN_EVT/%s",app->m_name);
|
||
|
app->EventCancelOpen(¶m->cancel_open);
|
||
|
break;
|
||
|
case ESP_GATTS_CLOSE_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_CLOSE_EVT/%s",app->m_name);
|
||
|
app->EventClose(¶m->close);
|
||
|
break;
|
||
|
case ESP_GATTS_LISTEN_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_LISTEN_EVT/%s",app->m_name);
|
||
|
app->EventListen();
|
||
|
break;
|
||
|
case ESP_GATTS_CONGEST_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_CONGEST_EVT/%s",app->m_name);
|
||
|
app->EventCongest(¶m->congest);
|
||
|
break;
|
||
|
case ESP_GATTS_CREATE_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_CREATE_EVT/%s status %d, service_handle %d",
|
||
|
app->m_name,
|
||
|
param->create.status, param->create.service_handle);
|
||
|
app->m_service_handle = param->create.service_handle;
|
||
|
app->EventCreate(¶m->add_attr_tab);
|
||
|
break;
|
||
|
case ESP_GATTS_ADD_CHAR_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_ADD_CHAR_EVT/%s status %d, attr_handle %d, service_handle %d",
|
||
|
app->m_name,
|
||
|
param->add_char.status,
|
||
|
param->add_char.attr_handle,
|
||
|
param->add_char.service_handle);
|
||
|
app->EventAddChar(¶m->add_char);
|
||
|
break;
|
||
|
case ESP_GATTS_ADD_CHAR_DESCR_EVT:
|
||
|
ESP_LOGI(TAG, "ESP_GATTS_ADD_CHAR_DESCR_EVT/%s status %d, attr_handle %d, service_handle %d",
|
||
|
app->m_name,
|
||
|
param->add_char.status, param->add_char.attr_handle,
|
||
|
param->add_char.service_handle);
|
||
|
app->EventAddCharDescr(¶m->add_char_descr);
|
||
|
break;
|
||
|
default:
|
||
|
ESP_LOGD(TAG, "GATTS PROFILE event = %d\n",event);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothGATTS::RegisterAllApps()
|
||
|
{
|
||
|
for (esp32bluetoothApp* app : m_apps)
|
||
|
{
|
||
|
esp_err_t ret = esp_ble_gatts_app_register(app->m_app_id);
|
||
|
if (ret)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "App %s register error, error code = %x",
|
||
|
app->m_name, ret);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG,"App %s registered successfully",app->m_name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothGATTS::UnregisterAllApps()
|
||
|
{
|
||
|
for (esp32bluetoothApp* app : m_apps)
|
||
|
{
|
||
|
esp_err_t ret = esp_ble_gatts_app_unregister(app->m_gatts_if);
|
||
|
if (ret)
|
||
|
{
|
||
|
ESP_LOGE(TAG, "App %s unregister error, error code = %x",
|
||
|
app->m_name, ret);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG,"App %s unregistered successfully",app->m_name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void esp32bluetoothGATTS::RegisterApp(esp32bluetoothApp* app)
|
||
|
{
|
||
|
m_apps.push_back(app);
|
||
|
app->m_app_slot = m_apps.size()-1;
|
||
|
}
|