2020-02-01 16:30:53 +00:00
# include "BluetoothUtil.h"
# include "BluetoothSoftwareUpdate.h"
# include <esp_gatt_defs.h>
# include <BLE2902.h>
# include <Arduino.h>
# include <Update.h>
2020-02-04 16:17:44 +00:00
# include "configuration.h"
2020-02-08 04:59:21 +00:00
# include "screen.h"
2020-02-01 16:30:53 +00:00
2020-02-23 18:49:37 +00:00
SimpleAllocator btPool ;
2020-02-08 04:59:21 +00:00
static BLECharacteristic SWVersionCharacteristic ( BLEUUID ( ( uint16_t ) ESP_GATT_UUID_SW_VERSION_STR ) , BLECharacteristic : : PROPERTY_READ ) ;
static BLECharacteristic ManufacturerCharacteristic ( BLEUUID ( ( uint16_t ) ESP_GATT_UUID_MANU_NAME ) , BLECharacteristic : : PROPERTY_READ ) ;
static BLECharacteristic HardwareVersionCharacteristic ( BLEUUID ( ( uint16_t ) ESP_GATT_UUID_HW_VERSION_STR ) , BLECharacteristic : : PROPERTY_READ ) ;
2020-02-01 16:30:53 +00:00
//static BLECharacteristic SerialNumberCharacteristic(BLEUUID((uint16_t) ESP_GATT_UUID_SERIAL_NUMBER_STR), BLECharacteristic::PROPERTY_READ);
/**
* Create standard device info service
* */
2020-02-19 00:18:01 +00:00
BLEService * createDeviceInfomationService ( BLEServer * server , std : : string hwVendor , std : : string swVersion , std : : string hwVersion = " " )
2020-02-08 04:59:21 +00:00
{
BLEService * deviceInfoService = server - > createService ( BLEUUID ( ( uint16_t ) ESP_GATT_UUID_DEVICE_INFO_SVC ) ) ;
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
/*
2020-02-01 16:30:53 +00:00
* Mandatory characteristic for device info service ?
BLECharacteristic * m_pnpCharacteristic = m_deviceInfoService - > createCharacteristic ( ESP_GATT_UUID_PNP_ID , BLECharacteristic : : PROPERTY_READ ) ;
uint8_t sig , uint16_t vid , uint16_t pid , uint16_t version ;
uint8_t pnp [ ] = { sig , ( uint8_t ) ( vid > > 8 ) , ( uint8_t ) vid , ( uint8_t ) ( pid > > 8 ) , ( uint8_t ) pid , ( uint8_t ) ( version > > 8 ) , ( uint8_t ) version } ;
m_pnpCharacteristic - > setValue ( pnp , sizeof ( pnp ) ) ;
*/
2020-02-08 04:59:21 +00:00
SWVersionCharacteristic . setValue ( swVersion ) ;
deviceInfoService - > addCharacteristic ( & SWVersionCharacteristic ) ;
ManufacturerCharacteristic . setValue ( hwVendor ) ;
deviceInfoService - > addCharacteristic ( & ManufacturerCharacteristic ) ;
2020-02-19 00:18:01 +00:00
if ( ! hwVersion . empty ( ) )
{
HardwareVersionCharacteristic . setValue ( hwVersion ) ;
deviceInfoService - > addCharacteristic ( & HardwareVersionCharacteristic ) ;
}
2020-02-08 04:59:21 +00:00
//SerialNumberCharacteristic.setValue("FIXME");
//deviceInfoService->addCharacteristic(&SerialNumberCharacteristic);
// m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a29, BLECharacteristic::PROPERTY_READ);
// m_manufacturerCharacteristic->setValue(name);
/* add these later?
2020-02-01 16:30:53 +00:00
ESP_GATT_UUID_SYSTEM_ID
*/
2020-02-08 04:59:21 +00:00
// caller must call service->start();
return deviceInfoService ;
2020-02-01 16:30:53 +00:00
}
bool _BLEClientConnected = false ;
2020-02-08 04:59:21 +00:00
class MyServerCallbacks : public BLEServerCallbacks
{
void onConnect ( BLEServer * pServer )
{
_BLEClientConnected = true ;
} ;
void onDisconnect ( BLEServer * pServer )
{
_BLEClientConnected = false ;
}
2020-02-01 16:30:53 +00:00
} ;
2020-02-23 18:49:37 +00:00
2020-02-01 16:30:53 +00:00
// Help routine to add a description to any BLECharacteristic and add it to the service
2020-02-08 04:59:21 +00:00
// We default to require an encrypted BOND for all these these characterstics
void addWithDesc ( BLEService * service , BLECharacteristic * c , const char * description )
{
c - > setAccessPermissions ( ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED ) ;
2020-02-23 18:49:37 +00:00
BLEDescriptor * desc = new ( btPool ) BLEDescriptor ( BLEUUID ( ( uint16_t ) ESP_GATT_UUID_CHAR_DESCRIPTION ) , strlen ( description ) + 1 ) ;
2020-02-04 01:13:41 +00:00
assert ( desc ) ;
2020-02-08 04:59:21 +00:00
desc - > setAccessPermissions ( ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED ) ;
2020-02-01 16:30:53 +00:00
desc - > setValue ( description ) ;
c - > addDescriptor ( desc ) ;
service - > addCharacteristic ( c ) ;
}
2020-02-08 04:59:21 +00:00
static BLECharacteristic BatteryLevelCharacteristic ( BLEUUID ( ( uint16_t ) ESP_GATT_UUID_BATTERY_LEVEL ) , BLECharacteristic : : PROPERTY_READ | BLECharacteristic : : PROPERTY_NOTIFY ) ;
2020-02-01 16:30:53 +00:00
2020-02-23 18:49:37 +00:00
2020-02-01 16:30:53 +00:00
/**
* Create a battery level service
*/
2020-02-08 04:59:21 +00:00
BLEService * createBatteryService ( BLEServer * server )
{
// Create the BLE Service
BLEService * pBattery = server - > createService ( BLEUUID ( ( uint16_t ) 0x180F ) ) ;
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
addWithDesc ( pBattery , & BatteryLevelCharacteristic , " Percentage 0 - 100 " ) ;
2020-02-23 18:49:37 +00:00
BatteryLevelCharacteristic . addDescriptor ( new ( btPool ) BLE2902 ( ) ) ; // Needed so clients can request notification
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
// I don't think we need to advertise this
// server->getAdvertising()->addServiceUUID(pBattery->getUUID());
pBattery - > start ( ) ;
2020-02-02 21:37:02 +00:00
2020-02-08 04:59:21 +00:00
return pBattery ;
2020-02-01 16:30:53 +00:00
}
2020-02-02 21:37:02 +00:00
/**
* Update the battery level we are currently telling clients .
* level should be a pct between 0 and 100
*/
2020-02-08 04:59:21 +00:00
void updateBatteryLevel ( uint8_t level )
{
// Pretend to update battery levels - fixme do elsewhere
BatteryLevelCharacteristic . setValue ( & level , 1 ) ;
BatteryLevelCharacteristic . notify ( ) ;
2020-02-02 21:37:02 +00:00
}
2020-02-08 04:59:21 +00:00
void dumpCharacteristic ( BLECharacteristic * c )
{
std : : string value = c - > getValue ( ) ;
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
if ( value . length ( ) > 0 )
{
DEBUG_MSG ( " New value: " ) ;
for ( int i = 0 ; i < value . length ( ) ; i + + )
DEBUG_MSG ( " %c " , value [ i ] ) ;
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
DEBUG_MSG ( " \n " ) ;
}
2020-02-01 16:30:53 +00:00
}
/** converting endianness pull out a 32 bit value */
2020-02-08 04:59:21 +00:00
uint32_t getValue32 ( BLECharacteristic * c , uint32_t defaultValue )
{
std : : string value = c - > getValue ( ) ;
uint32_t r = defaultValue ;
if ( value . length ( ) = = 4 )
r = value [ 0 ] | ( value [ 1 ] < < 8UL ) | ( value [ 2 ] < < 16UL ) | ( value [ 3 ] < < 24UL ) ;
return r ;
2020-02-01 16:30:53 +00:00
}
2020-02-08 04:59:21 +00:00
class MySecurity : public BLESecurityCallbacks
{
bool onConfirmPIN ( uint32_t pin )
{
Serial . printf ( " onConfirmPIN %u \n " , pin ) ;
return false ;
}
uint32_t onPassKeyRequest ( )
{
Serial . println ( " onPassKeyRequest " ) ;
return 123511 ; // not used
}
void onPassKeyNotify ( uint32_t pass_key )
{
Serial . printf ( " onPassKeyNotify %u \n " , pass_key ) ;
screen_start_bluetooth ( pass_key ) ;
}
bool onSecurityRequest ( )
{
Serial . println ( " onSecurityRequest " ) ;
return true ;
}
void onAuthenticationComplete ( esp_ble_auth_cmpl_t cmpl )
{
if ( cmpl . success )
{
uint16_t length ;
esp_ble_gap_get_whitelist_size ( & length ) ;
Serial . printf ( " onAuthenticationComplete -> success size: %d \n " , length ) ;
}
else
{
Serial . printf ( " onAuthenticationComplete -> fail %d \n " , cmpl . fail_reason ) ;
}
// Remove our custom screen
screen_set_frames ( ) ;
}
} ;
2020-02-14 22:00:08 +00:00
BLEServer * initBLE ( std : : string deviceName , std : : string hwVendor , std : : string swVersion , std : : string hwVersion )
2020-02-08 04:59:21 +00:00
{
BLEDevice : : init ( deviceName ) ;
BLEDevice : : setEncryptionLevel ( ESP_BLE_SEC_ENCRYPT ) ;
/*
* Required in authentication process to provide displaying and / or input passkey or yes / no butttons confirmation
*/
2020-02-23 18:49:37 +00:00
static MySecurity mySecurity ;
BLEDevice : : setSecurityCallbacks ( & mySecurity ) ;
2020-02-08 04:59:21 +00:00
// Create the BLE Server
BLEServer * pServer = BLEDevice : : createServer ( ) ;
2020-02-23 18:49:37 +00:00
static MyServerCallbacks myCallbacks ;
pServer - > setCallbacks ( & myCallbacks ) ;
2020-02-01 16:30:53 +00:00
2020-02-14 22:00:08 +00:00
BLEService * pDevInfo = createDeviceInfomationService ( pServer , hwVendor , swVersion , hwVersion ) ;
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
// We now let users create the battery service only if they really want (not all devices have a battery)
// BLEService *pBattery = createBatteryService(pServer);
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
BLEService * pUpdate = createUpdateService ( pServer ) ; // We need to advertise this so our android ble scan operation can see it
2020-02-19 00:18:01 +00:00
2020-02-13 19:53:46 +00:00
// It seems only one service can be advertised - so for now don't advertise our updater
// pServer->getAdvertising()->addServiceUUID(pUpdate->getUUID());
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
// start all our services (do this after creating all of them)
pDevInfo - > start ( ) ;
pUpdate - > start ( ) ;
2020-02-01 16:30:53 +00:00
2020-02-09 00:17:31 +00:00
// FIXME turn on this restriction only after the device is paired with a phone
// advert->setScanFilter(false, true); // We let anyone scan for us (FIXME, perhaps only allow that until we are paired with a phone and configured) but only let whitelist phones connect
2020-02-13 19:53:46 +00:00
2020-02-23 18:49:37 +00:00
static BLESecurity security ; // static to avoid allocs
BLESecurity * pSecurity = & security ;
2020-02-08 04:59:21 +00:00
pSecurity - > setCapability ( ESP_IO_CAP_OUT ) ;
pSecurity - > setAuthenticationMode ( ESP_LE_AUTH_REQ_SC_BOND ) ;
pSecurity - > setInitEncryptionKey ( ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK ) ;
2020-02-01 16:30:53 +00:00
2020-02-08 04:59:21 +00:00
return pServer ;
2020-02-01 16:30:53 +00:00
}
// Called from loop
2020-02-08 04:59:21 +00:00
void loopBLE ( )
{
bluetoothRebootCheck ( ) ;
2020-02-01 16:30:53 +00:00
}