Skip to content

Commit 28d49a0

Browse files
committed
Add ANCS example
1 parent b11d34e commit 28d49a0

4 files changed

Lines changed: 276 additions & 0 deletions

File tree

examples/ANCS/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# The following lines of boilerplate have to be in your project's
2+
# CMakeLists in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.5)
4+
5+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6+
project(ANCS)

examples/ANCS/main/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(COMPONENT_SRCS "main.cpp")
2+
set(COMPONENT_ADD_INCLUDEDIRS ".")
3+
4+
register_component()

examples/ANCS/main/main.cpp

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
// Original: https://github.com/mathcampbell/ANCS
2+
#include "NimBLEDevice.h"
3+
#include "driver/uart.h"
4+
5+
static NimBLEUUID ancsServiceUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0");
6+
static NimBLEUUID notificationSourceCharacteristicUUID("9FBF120D-6301-42D9-8C58-25E699A21DBD");
7+
static NimBLEUUID controlPointCharacteristicUUID("69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9");
8+
static NimBLEUUID dataSourceCharacteristicUUID("22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB");
9+
10+
static NimBLEClient *pClient;
11+
12+
uint8_t latestMessageID[4];
13+
bool pendingNotification = false;
14+
bool incomingCall = false;
15+
uint8_t acceptCall = 0;
16+
17+
static void initUart()
18+
{
19+
uart_config_t uartConfig{};
20+
uartConfig.baud_rate = 115200;
21+
uartConfig.data_bits = UART_DATA_8_BITS;
22+
uartConfig.parity = UART_PARITY_DISABLE;
23+
uartConfig.stop_bits = UART_STOP_BITS_1;
24+
uartConfig.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
25+
uartConfig.source_clk = UART_SCLK_DEFAULT;
26+
27+
uart_driver_install(UART_NUM_0, 256, 0, 0, nullptr, 0);
28+
uart_param_config(UART_NUM_0, &uartConfig);
29+
}
30+
31+
static void dataSourceNotifyCallback(NimBLERemoteCharacteristic *pDataSourceCharacteristic,
32+
uint8_t *pData,
33+
size_t length,
34+
bool isNotify)
35+
{
36+
for (int i = 0; i < length; i++)
37+
{
38+
if (i > 7)
39+
{
40+
printf("%c", pData[i]);
41+
}
42+
else
43+
{
44+
printf("%02X ", pData[i]);
45+
}
46+
}
47+
printf("\n");
48+
}
49+
50+
static void NotificationSourceNotifyCallback(NimBLERemoteCharacteristic *pNotificationSourceCharacteristic,
51+
uint8_t *pData,
52+
size_t length,
53+
bool isNotify)
54+
{
55+
if (pData[0] == 0)
56+
{
57+
printf("New notification!\n");
58+
latestMessageID[0] = pData[4];
59+
latestMessageID[1] = pData[5];
60+
latestMessageID[2] = pData[6];
61+
latestMessageID[3] = pData[7];
62+
63+
switch (pData[2])
64+
{
65+
case 0:
66+
printf("Category: Other\n");
67+
break;
68+
case 1:
69+
incomingCall = true;
70+
printf("Category: Incoming call\n");
71+
break;
72+
case 2:
73+
printf("Category: Missed call\n");
74+
break;
75+
case 3:
76+
printf("Category: Voicemail\n");
77+
break;
78+
case 4:
79+
printf("Category: Social\n");
80+
break;
81+
case 5:
82+
printf("Category: Schedule\n");
83+
break;
84+
case 6:
85+
printf("Category: Email\n");
86+
break;
87+
case 7:
88+
printf("Category: News\n");
89+
break;
90+
case 8:
91+
printf("Category: Health\n");
92+
break;
93+
case 9:
94+
printf("Category: Business\n");
95+
break;
96+
case 10:
97+
printf("Category: Location\n");
98+
break;
99+
case 11:
100+
printf("Category: Entertainment\n");
101+
break;
102+
default:
103+
break;
104+
}
105+
}
106+
else if (pData[0] == 1)
107+
{
108+
printf("Notification Modified!\n");
109+
if (pData[2] == 1)
110+
{
111+
printf("Call Changed!\n");
112+
}
113+
}
114+
else if (pData[0] == 2)
115+
{
116+
printf("Notification Removed!\n");
117+
if (pData[2] == 1)
118+
{
119+
printf("Call Gone!\n");
120+
}
121+
}
122+
pendingNotification = true;
123+
}
124+
125+
class ServerCallbacks : public NimBLEServerCallbacks
126+
{
127+
void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo)
128+
{
129+
printf("Client connected: %s\n", connInfo.getAddress().toString().c_str());
130+
pClient = pServer->getClient(connInfo);
131+
printf("Client connected!\n");
132+
}
133+
134+
void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
135+
{
136+
printf("Client disconnected: %s, reason: %d\n", connInfo.getAddress().toString().c_str(), reason);
137+
}
138+
} serverCallbacks;
139+
140+
extern "C" void app_main()
141+
{
142+
initUart();
143+
printf("Starting setup...\n");
144+
145+
NimBLEDevice::init("ANCS");
146+
NimBLEDevice::setSecurityAuth(true, true, true);
147+
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO);
148+
NimBLEDevice::setPower(9);
149+
150+
NimBLEServer *pServer = NimBLEDevice::createServer();
151+
pServer->setCallbacks(&serverCallbacks);
152+
pServer->advertiseOnDisconnect(true);
153+
154+
NimBLEAdvertising *pAdvertising = pServer->getAdvertising();
155+
NimBLEAdvertisementData advData{};
156+
advData.setFlags(0x06);
157+
advData.addServiceUUID(ancsServiceUUID);
158+
pAdvertising->setAdvertisementData(advData);
159+
pAdvertising->start();
160+
161+
printf("Advertising started!\n");
162+
163+
while (1)
164+
{
165+
if (pClient != nullptr && pClient->isConnected())
166+
{
167+
auto pAncsService = pClient->getService(ancsServiceUUID);
168+
if (pAncsService == nullptr)
169+
{
170+
printf("Failed to find our service UUID: %s\n", ancsServiceUUID.toString().c_str());
171+
continue;
172+
}
173+
// Obtain a reference to the characteristic in the service of the remote BLE server.
174+
auto pNotificationSourceCharacteristic = pAncsService->getCharacteristic(notificationSourceCharacteristicUUID);
175+
if (pNotificationSourceCharacteristic == nullptr)
176+
{
177+
printf("Failed to find our characteristic UUID: %s\n",
178+
notificationSourceCharacteristicUUID.toString().c_str());
179+
continue;
180+
}
181+
// Obtain a reference to the characteristic in the service of the remote BLE server.
182+
auto pControlPointCharacteristic = pAncsService->getCharacteristic(controlPointCharacteristicUUID);
183+
if (pControlPointCharacteristic == nullptr)
184+
{
185+
printf("Failed to find our characteristic UUID: %s\n",
186+
controlPointCharacteristicUUID.toString().c_str());
187+
continue;
188+
}
189+
// Obtain a reference to the characteristic in the service of the remote BLE server.
190+
auto pDataSourceCharacteristic = pAncsService->getCharacteristic(dataSourceCharacteristicUUID);
191+
if (pDataSourceCharacteristic == nullptr)
192+
{
193+
printf("Failed to find our characteristic UUID: %s\n", dataSourceCharacteristicUUID.toString().c_str());
194+
continue;
195+
}
196+
pDataSourceCharacteristic->subscribe(true, dataSourceNotifyCallback);
197+
pNotificationSourceCharacteristic->subscribe(true, NotificationSourceNotifyCallback);
198+
199+
while (1)
200+
{
201+
if (pendingNotification || incomingCall)
202+
{
203+
// CommandID: CommandIDGetNotificationAttributes
204+
// 32bit uid
205+
// AttributeID
206+
printf("Requesting details...\n");
207+
uint8_t val[8] =
208+
{0x0, latestMessageID[0], latestMessageID[1], latestMessageID[2], latestMessageID[3], 0x0, 0x0, 0x10};
209+
pControlPointCharacteristic->writeValue(val, 6, true); // Identifier
210+
val[5] = 0x1;
211+
pControlPointCharacteristic->writeValue(val, 8, true); // Title
212+
val[5] = 0x3;
213+
pControlPointCharacteristic->writeValue(val, 8, true); // Message
214+
val[5] = 0x5;
215+
pControlPointCharacteristic->writeValue(val, 6, true); // Date
216+
217+
while (incomingCall)
218+
{
219+
int bytesRead = uart_read_bytes(UART_NUM_0, &acceptCall, 1, 0);
220+
if (bytesRead > 0)
221+
{
222+
printf("%c\n", (char)acceptCall);
223+
}
224+
225+
if (acceptCall == 49)
226+
{ // call accepted , get number 1 from serial
227+
const uint8_t vResponse[] =
228+
{0x02, latestMessageID[0], latestMessageID[1], latestMessageID[2], latestMessageID[3], 0x00};
229+
pControlPointCharacteristic->writeValue((uint8_t *)vResponse, 6, true);
230+
231+
acceptCall = 0;
232+
// incomingCall = false;
233+
}
234+
else if (acceptCall == 48)
235+
{ // call rejected , get number 0 from serial
236+
const uint8_t vResponse[] =
237+
{0x02, latestMessageID[0], latestMessageID[1], latestMessageID[2], latestMessageID[3], 0x01};
238+
pControlPointCharacteristic->writeValue((uint8_t *)vResponse, 6, true);
239+
240+
acceptCall = 0;
241+
incomingCall = false;
242+
}
243+
vTaskDelay(10 / portTICK_PERIOD_MS);
244+
}
245+
246+
pendingNotification = false;
247+
}
248+
vTaskDelay(10 / portTICK_PERIOD_MS);
249+
}
250+
}
251+
vTaskDelay(10 / portTICK_PERIOD_MS);
252+
}
253+
}

examples/ANCS/sdkconfig.defaults

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Override some defaults so BT stack is enabled
2+
# in this example
3+
4+
#
5+
# BT config
6+
#
7+
CONFIG_BT_ENABLED=y
8+
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
9+
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
10+
CONFIG_BTDM_CTRL_MODE_BTDM=n
11+
CONFIG_BT_BLUEDROID_ENABLED=n
12+
CONFIG_BT_NIMBLE_ENABLED=y
13+
CONFIG_BT_NIMBLE_NVS_PERSIST=y

0 commit comments

Comments
 (0)