mirror of
https://github.com/Smartphone-Companions/ESP32-ANCS-Notifications.git
synced 2025-01-22 11:28:29 +00:00
Added non-functional ANCS interface. Needs to be refactored to be a class.
This commit is contained in:
parent
60d8063232
commit
40035b5d18
@ -3,9 +3,11 @@
|
||||
|
||||
#include "esp32notifications.h"
|
||||
|
||||
// Different hardware presets; feel free to add your own board layout.
|
||||
// You will need to add these hardware buttons to your dev board.
|
||||
// See the ESP32 pinout to choose a free GPIO pin.
|
||||
// Different hardware presets; uncomment the correct device.
|
||||
// Or feel free to add your own board layout for your specific hardware.
|
||||
// See the ESP32 pinout to choose a free GPIO pin on your hardware.
|
||||
|
||||
// An inexpensive and easy-to build open-source smartwatch platform https://github.com/jhud/hackwatch
|
||||
#define HARDWARE_HACKWATCH
|
||||
|
||||
#ifdef HARDWARE_HACKWATCH
|
||||
@ -19,6 +21,8 @@
|
||||
|
||||
BLENotifications notifications;
|
||||
|
||||
// This callback will be called when a Bluetooth LE connection is made or broken.
|
||||
// You can update the device's UI or take other action here.
|
||||
void onBLEStateChanged(BLENotifications::State state) {
|
||||
switch(state) {
|
||||
case BLENotifications::StateConnected:
|
||||
@ -32,11 +36,13 @@ void onBLEStateChanged(BLENotifications::State state) {
|
||||
}
|
||||
|
||||
|
||||
// A notification arrived from the mobile device, ie a social media notification or incoming call.
|
||||
void onNotificationArrived() {
|
||||
Serial.println("Got notification.");
|
||||
}
|
||||
|
||||
|
||||
// Called once when the device first starts up
|
||||
void setup() {
|
||||
// Button configuration
|
||||
pinMode(BUTTON_A, INPUT_PULLUP);
|
||||
@ -51,14 +57,14 @@ void setup() {
|
||||
Serial.println("BLENotifications BLE ANCS on ESP32 Example");
|
||||
Serial.println("------------------------------------------");
|
||||
|
||||
notifications.begin("deviceName");
|
||||
// Set up the BLENotification library
|
||||
notifications.begin("BLEConnection device name");
|
||||
notifications.setConnectionStateChangedCallback(onBLEStateChanged);
|
||||
notifications.setNotificationCallback(onNotificationArrived);
|
||||
}
|
||||
|
||||
|
||||
void checkButtons() {
|
||||
|
||||
if (digitalRead(BUTTON_A) == LOW) {
|
||||
Serial.println("Positive action.");
|
||||
notifications.actionPositive();
|
||||
|
192
src/ancs_ble_client.cpp
Normal file
192
src/ancs_ble_client.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
// Based on the ANCS work of https://github.com/S-March
|
||||
|
||||
#include "ble_security.h"
|
||||
#include "ancs_ble_client.h"
|
||||
|
||||
#include "BLEAddress.h"
|
||||
#include "BLEDevice.h"
|
||||
#include "BLEClient.h"
|
||||
#include "BLEUtils.h"
|
||||
#include "BLE2902.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <Arduino.h> // Only for development
|
||||
|
||||
static char LOG_TAG[] = "ancs_ble_client";
|
||||
|
||||
// Fixed service IDs for the Apple ANCS service
|
||||
const BLEUUID notificationSourceCharacteristicUUID("9FBF120D-6301-42D9-8C58-25E699A21DBD");
|
||||
const BLEUUID controlPointCharacteristicUUID("69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9");
|
||||
const BLEUUID dataSourceCharacteristicUUID("22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB");
|
||||
const BLEUUID ancsServiceUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0");
|
||||
|
||||
|
||||
// @todo - make into class or remove global data
|
||||
uint8_t latestMessageID[4];
|
||||
boolean pendingNotification = false;
|
||||
BLERemoteCharacteristic* pControlPointCharacteristic;
|
||||
|
||||
#define MESSAGE_TITLE 1
|
||||
#define MESSAGE_BODY 3
|
||||
|
||||
static void dataSourceNotifyCallback(
|
||||
BLERemoteCharacteristic* pDataSourceCharacteristic,
|
||||
uint8_t* pData,
|
||||
size_t length,
|
||||
bool isNotify) {
|
||||
Serial.print("Notify callback for characteristic ");
|
||||
Serial.print(pDataSourceCharacteristic->getUUID().toString().c_str());
|
||||
Serial.print(" of data length ");
|
||||
Serial.println(length);
|
||||
for(int i = 0; i < length; i++){
|
||||
if(i > 7){
|
||||
Serial.write(pData[i]);
|
||||
}
|
||||
else{
|
||||
Serial.print(pData[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
if ((pData[5] == MESSAGE_BODY || pData[5] == MESSAGE_TITLE) /*&& onMsgReceived*/) {
|
||||
pData[length]=0;
|
||||
//onMsgReceived(pData[5], (char*)pData+8); // @todo send msg received cb
|
||||
}
|
||||
}
|
||||
|
||||
static void notificationSourceNotifyCallback(
|
||||
BLERemoteCharacteristic* pNotificationSourceCharacteristic,
|
||||
uint8_t* pData,
|
||||
size_t length,
|
||||
bool isNotify)
|
||||
{
|
||||
if(pData[0]==0)
|
||||
{
|
||||
|
||||
Serial.println("New notification!");
|
||||
//Serial.println(pNotificationSourceCharacteristic->getUUID().toString().c_str());
|
||||
latestMessageID[0] = pData[4];
|
||||
latestMessageID[1] = pData[5];
|
||||
latestMessageID[2] = pData[6];
|
||||
latestMessageID[3] = pData[7];
|
||||
|
||||
switch(pData[2])
|
||||
{
|
||||
case 0:
|
||||
Serial.println("Category: Other");
|
||||
break;
|
||||
case 1:
|
||||
Serial.println("Category: Incoming call");
|
||||
break;
|
||||
case 2:
|
||||
Serial.println("Category: Missed call");
|
||||
break;
|
||||
case 3:
|
||||
Serial.println("Category: Voicemail");
|
||||
break;
|
||||
case 4:
|
||||
Serial.println("Category: Social");
|
||||
break;
|
||||
case 5:
|
||||
Serial.println("Category: Schedule");
|
||||
break;
|
||||
case 6:
|
||||
Serial.println("Category: Email");
|
||||
break;
|
||||
case 7:
|
||||
Serial.println("Category: News");
|
||||
break;
|
||||
case 8:
|
||||
Serial.println("Category: Health");
|
||||
break;
|
||||
case 9:
|
||||
Serial.println("Category: Business");
|
||||
break;
|
||||
case 10:
|
||||
Serial.println("Category: Location");
|
||||
break;
|
||||
case 11:
|
||||
Serial.println("Category: Entertainment");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pendingNotification = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Become a BLE client to a remote BLE server. We are passed in the address of the BLE server
|
||||
* as the input parameter when the task is created.
|
||||
*/
|
||||
void ancs_ble_client_init(const BLEAddress* address) {
|
||||
BLEClient* pClient = BLEDevice::createClient();
|
||||
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
|
||||
BLEDevice::setSecurityCallbacks(new NotificationSecurityCallbacks()); // @todo memory leak?
|
||||
|
||||
BLESecurity *pSecurity = new BLESecurity();
|
||||
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
|
||||
pSecurity->setCapability(ESP_IO_CAP_IO);
|
||||
pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
|
||||
// Connect to the remove BLE Server.
|
||||
pClient->connect(*address);
|
||||
|
||||
/** BEGIN ANCS SERVICE **/
|
||||
// Obtain a reference to the service we are after in the remote BLE server.
|
||||
BLERemoteService* pAncsService = pClient->getService(ancsServiceUUID);
|
||||
if (pAncsService == nullptr) {
|
||||
ESP_LOGD(LOG_TAG, "Failed to find service UUID ancsServiceUUID.");
|
||||
return;
|
||||
}
|
||||
// Obtain a reference to the characteristic in the service of the remote BLE server.
|
||||
BLERemoteCharacteristic* pNotificationSourceCharacteristic = pAncsService->getCharacteristic(notificationSourceCharacteristicUUID);
|
||||
if (pNotificationSourceCharacteristic == nullptr) {
|
||||
ESP_LOGD(LOG_TAG, "Failed to find characteristic UUID notificationSourceCharacteristicUUID");
|
||||
return;
|
||||
}
|
||||
// Obtain a reference to the characteristic in the service of the remote BLE server.
|
||||
pControlPointCharacteristic = pAncsService->getCharacteristic(controlPointCharacteristicUUID);
|
||||
if (pControlPointCharacteristic == nullptr) {
|
||||
ESP_LOGD(LOG_TAG, "Failed to find characteristic UUID: controlPointCharacteristicUUID");
|
||||
return;
|
||||
}
|
||||
// Obtain a reference to the characteristic in the service of the remote BLE server.
|
||||
BLERemoteCharacteristic* pDataSourceCharacteristic = pAncsService->getCharacteristic(dataSourceCharacteristicUUID);
|
||||
if (pDataSourceCharacteristic == nullptr) {
|
||||
ESP_LOGD(LOG_TAG, "Failed to find characteristic UUID dataSourceCharacteristicUUID");
|
||||
return;
|
||||
}
|
||||
const uint8_t v[]={0x1,0x0};
|
||||
pDataSourceCharacteristic->registerForNotify(dataSourceNotifyCallback);
|
||||
pDataSourceCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)v,2,true);
|
||||
pNotificationSourceCharacteristic->registerForNotify(notificationSourceNotifyCallback);
|
||||
pNotificationSourceCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)v,2,true);
|
||||
/** END ANCS SERVICE **/
|
||||
}
|
||||
|
||||
BLEUUID getAncsServiceUUID() {
|
||||
return ancsServiceUUID;
|
||||
}
|
||||
|
||||
void ancs_ble_client_update() {
|
||||
if(pendingNotification == true){
|
||||
// CommandID: CommandIDGetNotificationAttributes
|
||||
// 32bit uid
|
||||
// AttributeID
|
||||
ESP_LOGD(LOG_TAG, "Requesting details...");
|
||||
const uint8_t vIdentifier[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x0};
|
||||
pControlPointCharacteristic->writeValue((uint8_t*)vIdentifier,6,true);
|
||||
const uint8_t vTitle[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x1, 0x0, 0x10};
|
||||
pControlPointCharacteristic->writeValue((uint8_t*)vTitle,8,true);
|
||||
const uint8_t vMessage[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x3, 0x0, 0x10};
|
||||
pControlPointCharacteristic->writeValue((uint8_t*)vMessage,8,true);
|
||||
const uint8_t vDate[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x5};
|
||||
pControlPointCharacteristic->writeValue((uint8_t*)vDate,6,true);
|
||||
pendingNotification = false;
|
||||
}
|
||||
delay(100); //does not work without small delay
|
||||
}
|
18
src/ancs_ble_client.h
Normal file
18
src/ancs_ble_client.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef ANCS_BLE_CLIENT_H_
|
||||
#define ANCS_BLE_CLIENT_H_
|
||||
|
||||
class BLEAddress;
|
||||
class BLERemoteCharacteristic;
|
||||
|
||||
|
||||
#include "BLEUUID.h"
|
||||
|
||||
/**
|
||||
* Internal module for creating and managing an ANCS client connection.
|
||||
*/
|
||||
// @todo - should definitely be a class
|
||||
void ancs_ble_client_init(const BLEAddress* address);
|
||||
void ancs_ble_client_update();
|
||||
BLEUUID getAncsServiceUUID();
|
||||
|
||||
#endif // ANCS_BLE_CLIENT_H_
|
36
src/ble_security.cpp
Normal file
36
src/ble_security.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
#include "ble_security.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
static char LOG_TAG[] = "NotificationSecurityCallbacks";
|
||||
|
||||
|
||||
|
||||
uint32_t NotificationSecurityCallbacks::onPassKeyRequest(){
|
||||
ESP_LOGI(LOG_TAG, "PassKeyRequest");
|
||||
return 123456;
|
||||
}
|
||||
|
||||
void NotificationSecurityCallbacks::onPassKeyNotify(uint32_t pass_key){
|
||||
ESP_LOGI(LOG_TAG, "On passkey Notify number:%d", pass_key);
|
||||
}
|
||||
|
||||
bool NotificationSecurityCallbacks::onSecurityRequest(){
|
||||
ESP_LOGI(LOG_TAG, "On Security Request");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NotificationSecurityCallbacks::onConfirmPIN(unsigned int){
|
||||
ESP_LOGI(LOG_TAG, "On Confrimed Pin Request");
|
||||
return true;
|
||||
}
|
||||
|
||||
void NotificationSecurityCallbacks::onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
|
||||
ESP_LOGI(LOG_TAG, "Starting BLE work!");
|
||||
if(cmpl.success){
|
||||
uint16_t length;
|
||||
esp_ble_gap_get_whitelist_size(&length);
|
||||
ESP_LOGD(LOG_TAG, "size: %d", length);
|
||||
}
|
||||
}
|
19
src/ble_security.h
Normal file
19
src/ble_security.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef BLE_SECURITY_H_
|
||||
#define BLE_SECURITY_H_
|
||||
|
||||
#include "BLESecurity.h"
|
||||
|
||||
class NotificationSecurityCallbacks : public BLESecurityCallbacks {
|
||||
|
||||
uint32_t onPassKeyRequest();
|
||||
|
||||
void onPassKeyNotify(uint32_t pass_key);
|
||||
|
||||
bool onSecurityRequest();
|
||||
|
||||
bool onConfirmPIN(unsigned int);
|
||||
|
||||
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl);
|
||||
};
|
||||
|
||||
#endif // BLE_SECURITY_H_
|
@ -1,6 +1,8 @@
|
||||
// Based on https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/ble/ble_ancs
|
||||
|
||||
#include "esp32notifications.h"
|
||||
#include "ancs_ble_client.h"
|
||||
#include "ble_security.h"
|
||||
|
||||
#include "BLEAddress.h"
|
||||
#include "BLEDevice.h"
|
||||
@ -13,37 +15,7 @@
|
||||
|
||||
static char LOG_TAG[] = "BLENotifications";
|
||||
|
||||
class MySecurity : public BLESecurityCallbacks {
|
||||
|
||||
uint32_t onPassKeyRequest(){
|
||||
ESP_LOGI(LOG_TAG, "PassKeyRequest");
|
||||
return 123456;
|
||||
}
|
||||
|
||||
void onPassKeyNotify(uint32_t pass_key){
|
||||
ESP_LOGI(LOG_TAG, "On passkey Notify number:%d", pass_key);
|
||||
}
|
||||
|
||||
bool onSecurityRequest(){
|
||||
ESP_LOGI(LOG_TAG, "On Security Request");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onConfirmPIN(unsigned int){
|
||||
ESP_LOGI(LOG_TAG, "On Confrimed Pin Request");
|
||||
return true;
|
||||
}
|
||||
|
||||
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
|
||||
ESP_LOGI(LOG_TAG, "Starting BLE work!");
|
||||
if(cmpl.success){
|
||||
uint16_t length;
|
||||
esp_ble_gap_get_whitelist_size(&length);
|
||||
ESP_LOGD(LOG_TAG, "size: %d", length);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern const BLEUUID ancsServiceUUID;
|
||||
|
||||
class MyServerCallbacks: public BLEServerCallbacks {
|
||||
private:
|
||||
@ -64,22 +36,28 @@ public:
|
||||
Serial.println("**Device connected**");
|
||||
gatts_connect_evt_param * connectEventParam = (gatts_connect_evt_param *) param;
|
||||
Serial.println(BLEAddress(connectEventParam->remote_bda).toString().c_str());
|
||||
/*MyClient* pMyClient = new MyClient();
|
||||
pMyClient->setStackSize(18000);
|
||||
pMyClient->start(new BLEAddress(BLEDevice::m_remoteBda));*/ // @todo - memory leak?
|
||||
//ANCSBLEClient* pMyClient = new ANCSBLEClient(); // @todo memory leak?
|
||||
//pMyClient->setStackSize(18000); // @todo not needed?
|
||||
ancs_ble_client_init(new BLEAddress(connectEventParam->remote_bda)); // @todo - memory leak?
|
||||
|
||||
delay(1000);
|
||||
|
||||
// Grab any pending notifications as a test
|
||||
ancs_ble_client_update();
|
||||
|
||||
if (instance->cbStateChanged) {
|
||||
instance->cbStateChanged(BLENotifications::StateConnected);
|
||||
}
|
||||
};
|
||||
|
||||
void onDisconnect(BLEServer* pServer) {
|
||||
ESP_LOGI(LOG_TAG, "Device disconnected");
|
||||
Serial.println("**Device disconnected**");
|
||||
if (instance->cbStateChanged) {
|
||||
instance->cbStateChanged(BLENotifications::StateDisconnected);
|
||||
}
|
||||
// @todo, disconnect, free stack?
|
||||
}
|
||||
void onDisconnect(BLEServer* pServer) {
|
||||
ESP_LOGI(LOG_TAG, "Device disconnected");
|
||||
Serial.println("**Device disconnected**");
|
||||
if (instance->cbStateChanged) {
|
||||
instance->cbStateChanged(BLENotifications::StateDisconnected);
|
||||
}
|
||||
// @todo, disconnect, free stack?
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -96,7 +74,6 @@ bool BLENotifications::begin(const char * name) {
|
||||
server = BLEDevice::createServer();
|
||||
server->setCallbacks(new MyServerCallbacks(this));
|
||||
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
|
||||
BLEDevice::setSecurityCallbacks(new MySecurity());
|
||||
|
||||
startAdvertising();
|
||||
}
|
||||
@ -122,11 +99,13 @@ void BLENotifications::actionNegative() {
|
||||
}
|
||||
|
||||
void BLENotifications::startAdvertising() {
|
||||
// Start soliciting ANCS
|
||||
BLEDevice::setSecurityCallbacks(new NotificationSecurityCallbacks()); // @todo memory leak?
|
||||
|
||||
// Start soliciting the Apple ANCS service and make the device visible to searches on iOS (from Apple ANCS documentation)
|
||||
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
|
||||
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
|
||||
oAdvertisementData.setFlags(0x01);
|
||||
oAdvertisementData.setServiceSolicitation(BLEUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0"));
|
||||
oAdvertisementData.setServiceSolicitation(getAncsServiceUUID());
|
||||
pAdvertising->setAdvertisementData(oAdvertisementData);
|
||||
|
||||
// Set security
|
||||
|
Loading…
Reference in New Issue
Block a user