/* ; 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 #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; }