BLE Current Time Service

BLE Current Time Service (CTS) implementation.

supported only "Current Time" Characteristics.

https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx

I don't have a device corresponding to the CTS, I cannot check it. x)

Committer:
ohneta
Date:
Sat Oct 17 17:04:10 2015 +0000
Revision:
1:c4b8028471f9
Parent:
0:8c79e11bc3a1
Child:
2:27a6c04cadb2
????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ohneta 0:8c79e11bc3a1 1 /*
ohneta 0:8c79e11bc3a1 2 * BLE Current Time Service (subset)
ohneta 0:8c79e11bc3a1 3 *
ohneta 0:8c79e11bc3a1 4 * by ohneta/ Oct. 2015
ohneta 0:8c79e11bc3a1 5 */
ohneta 0:8c79e11bc3a1 6 #ifndef __BLE_CURRENT_TIME_SERVICE_H__
ohneta 0:8c79e11bc3a1 7 #define __BLE_CURRENT_TIME_SERVICE_H__
ohneta 0:8c79e11bc3a1 8
ohneta 1:c4b8028471f9 9 #include "ble/BLE.h"
ohneta 0:8c79e11bc3a1 10 //extern Serial pc;
ohneta 0:8c79e11bc3a1 11
ohneta 0:8c79e11bc3a1 12
ohneta 0:8c79e11bc3a1 13 enum BLE_DayofWeek {
ohneta 0:8c79e11bc3a1 14 notknown = 0,
ohneta 0:8c79e11bc3a1 15 Monday = 1,
ohneta 0:8c79e11bc3a1 16 Tuesday,
ohneta 0:8c79e11bc3a1 17 Wednesday,
ohneta 0:8c79e11bc3a1 18 Thursday,
ohneta 0:8c79e11bc3a1 19 Friday,
ohneta 0:8c79e11bc3a1 20 Saturday,
ohneta 0:8c79e11bc3a1 21 Sunday
ohneta 0:8c79e11bc3a1 22 };
ohneta 0:8c79e11bc3a1 23
ohneta 0:8c79e11bc3a1 24 typedef struct {
ohneta 0:8c79e11bc3a1 25 uint16_t year;
ohneta 0:8c79e11bc3a1 26 uint8_t month;
ohneta 0:8c79e11bc3a1 27 uint8_t day;
ohneta 0:8c79e11bc3a1 28 uint8_t hours;
ohneta 0:8c79e11bc3a1 29 uint8_t minutes;
ohneta 0:8c79e11bc3a1 30 uint8_t seconds;
ohneta 0:8c79e11bc3a1 31 } BLE_DateTime;
ohneta 0:8c79e11bc3a1 32
ohneta 0:8c79e11bc3a1 33 typedef struct : BLE_DateTime {
ohneta 0:8c79e11bc3a1 34 BLE_DayofWeek dayOfWeek;
ohneta 0:8c79e11bc3a1 35 } BLE_DayDateTime;
ohneta 0:8c79e11bc3a1 36
ohneta 0:8c79e11bc3a1 37 typedef struct BEL_ExactTime256 : BLE_DayDateTime {
ohneta 0:8c79e11bc3a1 38 uint8_t fractions256;
ohneta 0:8c79e11bc3a1 39 } BEL_ExactTime256;
ohneta 0:8c79e11bc3a1 40
ohneta 0:8c79e11bc3a1 41 typedef struct BEL_CurrentTime : BEL_ExactTime256 {
ohneta 0:8c79e11bc3a1 42 uint8_t adjustReason;
ohneta 0:8c79e11bc3a1 43 } BEL_CurrentTime;
ohneta 0:8c79e11bc3a1 44
ohneta 0:8c79e11bc3a1 45 #define BLE_CURRENT_TIME_CHAR_VALUE_SIZE 10
ohneta 0:8c79e11bc3a1 46
ohneta 0:8c79e11bc3a1 47 /**
ohneta 0:8c79e11bc3a1 48 *
ohneta 0:8c79e11bc3a1 49 */
ohneta 0:8c79e11bc3a1 50 class CurrentTimeService {
ohneta 0:8c79e11bc3a1 51
ohneta 0:8c79e11bc3a1 52 protected:
ohneta 0:8c79e11bc3a1 53 Ticker ticker;
ohneta 0:8c79e11bc3a1 54
ohneta 0:8c79e11bc3a1 55 /**
ohneta 0:8c79e11bc3a1 56 * ticker callback.
ohneta 0:8c79e11bc3a1 57 * interval = 1sec
ohneta 0:8c79e11bc3a1 58 */
ohneta 0:8c79e11bc3a1 59 void epochtimePeriodicCallback(void)
ohneta 0:8c79e11bc3a1 60 {
ohneta 0:8c79e11bc3a1 61 time_t tmpEpochTime = epochTimeByDateTimeBuffer();
ohneta 0:8c79e11bc3a1 62 tmpEpochTime++;
ohneta 0:8c79e11bc3a1 63 dataTimeBufferByEpochTime(&tmpEpochTime);
ohneta 0:8c79e11bc3a1 64 }
ohneta 0:8c79e11bc3a1 65
ohneta 0:8c79e11bc3a1 66 void dataTimeBufferByEpochTime(time_t *epochTime)
ohneta 0:8c79e11bc3a1 67 {
ohneta 0:8c79e11bc3a1 68 struct tm *tmPtr = localtime(epochTime);
ohneta 0:8c79e11bc3a1 69
ohneta 0:8c79e11bc3a1 70 *(uint16_t *)&valueBytes[0] = tmPtr->tm_year + 1900;
ohneta 0:8c79e11bc3a1 71 valueBytes[2] = tmPtr->tm_mon + 1;
ohneta 0:8c79e11bc3a1 72 valueBytes[3] = tmPtr->tm_mday;
ohneta 0:8c79e11bc3a1 73 valueBytes[4] = tmPtr->tm_hour;
ohneta 0:8c79e11bc3a1 74 valueBytes[5] = tmPtr->tm_min;
ohneta 0:8c79e11bc3a1 75 valueBytes[6] = tmPtr->tm_sec;
ohneta 0:8c79e11bc3a1 76 valueBytes[7] = (BLE_DayofWeek)((tmPtr->tm_wday == 0) ? 7 : tmPtr->tm_wday);
ohneta 0:8c79e11bc3a1 77 valueBytes[8] = 0x00;
ohneta 0:8c79e11bc3a1 78 valueBytes[9] = 0x00;
ohneta 0:8c79e11bc3a1 79
ohneta 0:8c79e11bc3a1 80 ble.gattServer().write(currentTimeCharacteristic.getValueHandle(), valueBytes, BLE_CURRENT_TIME_CHAR_VALUE_SIZE);
ohneta 0:8c79e11bc3a1 81 }
ohneta 0:8c79e11bc3a1 82
ohneta 0:8c79e11bc3a1 83 time_t epochTimeByDateTimeBuffer()
ohneta 0:8c79e11bc3a1 84 {
ohneta 0:8c79e11bc3a1 85 struct tm timep;
ohneta 0:8c79e11bc3a1 86 {
ohneta 0:8c79e11bc3a1 87 timep.tm_year = *(uint16_t *)&valueBytes[0] - 1900;
ohneta 0:8c79e11bc3a1 88 timep.tm_mon = valueBytes[2] - 1;
ohneta 0:8c79e11bc3a1 89 timep.tm_mday = valueBytes[3];
ohneta 0:8c79e11bc3a1 90 timep.tm_hour = valueBytes[4];
ohneta 0:8c79e11bc3a1 91 timep.tm_min = valueBytes[5];
ohneta 0:8c79e11bc3a1 92 timep.tm_sec = valueBytes[6];
ohneta 0:8c79e11bc3a1 93 timep.tm_isdst = 0;
ohneta 0:8c79e11bc3a1 94 }
ohneta 0:8c79e11bc3a1 95 time_t epochTime = mktime(&timep);
ohneta 0:8c79e11bc3a1 96
ohneta 0:8c79e11bc3a1 97 return epochTime;
ohneta 0:8c79e11bc3a1 98 }
ohneta 0:8c79e11bc3a1 99
ohneta 0:8c79e11bc3a1 100 public:
ohneta 0:8c79e11bc3a1 101 //------------------------------------------------------------------------------------
ohneta 0:8c79e11bc3a1 102 /**
ohneta 0:8c79e11bc3a1 103 *
ohneta 0:8c79e11bc3a1 104 */
ohneta 0:8c79e11bc3a1 105 CurrentTimeService(BLE &_ble, BLE_DateTime &initialDateTime) :
ohneta 0:8c79e11bc3a1 106 ble(_ble),
ohneta 0:8c79e11bc3a1 107 currentTimeCharacteristic( GattCharacteristic::UUID_CURRENT_TIME_CHAR,
ohneta 0:8c79e11bc3a1 108 valueBytes, BLE_CURRENT_TIME_CHAR_VALUE_SIZE, BLE_CURRENT_TIME_CHAR_VALUE_SIZE,
ohneta 0:8c79e11bc3a1 109 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
ohneta 0:8c79e11bc3a1 110 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
ohneta 0:8c79e11bc3a1 111 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
ohneta 0:8c79e11bc3a1 112 )
ohneta 0:8c79e11bc3a1 113 {
ohneta 0:8c79e11bc3a1 114 writeDateTime(initialDateTime);
ohneta 0:8c79e11bc3a1 115 ticker.attach(this, &CurrentTimeService::epochtimePeriodicCallback, 1.0);
ohneta 0:8c79e11bc3a1 116
ohneta 0:8c79e11bc3a1 117 GattCharacteristic *charsTable[] = {&currentTimeCharacteristic};
ohneta 0:8c79e11bc3a1 118 GattService currentTimeService(GattService::UUID_CURRENT_TIME_SERVICE, charsTable, sizeof(charsTable) / sizeof(GattCharacteristic *) );
ohneta 0:8c79e11bc3a1 119
ohneta 0:8c79e11bc3a1 120 ble.addService(currentTimeService);
ohneta 0:8c79e11bc3a1 121 ble.onDataWritten(this, &CurrentTimeService::onDataWritten);
ohneta 0:8c79e11bc3a1 122 }
ohneta 0:8c79e11bc3a1 123
ohneta 0:8c79e11bc3a1 124 /**
ohneta 0:8c79e11bc3a1 125 */
ohneta 0:8c79e11bc3a1 126 void writeDateTime(BLE_DateTime &dateTime)
ohneta 0:8c79e11bc3a1 127 {
ohneta 0:8c79e11bc3a1 128 *(uint16_t *)&valueBytes[0] = dateTime.year;
ohneta 0:8c79e11bc3a1 129 valueBytes[2] = dateTime.month;
ohneta 0:8c79e11bc3a1 130 valueBytes[3] = dateTime.day;
ohneta 0:8c79e11bc3a1 131 valueBytes[4] = dateTime.hours;
ohneta 0:8c79e11bc3a1 132 valueBytes[5] = dateTime.minutes;
ohneta 0:8c79e11bc3a1 133 valueBytes[6] = dateTime.seconds;
ohneta 0:8c79e11bc3a1 134
ohneta 0:8c79e11bc3a1 135 // not support
ohneta 0:8c79e11bc3a1 136 valueBytes[7] = 0x00; // day of week
ohneta 0:8c79e11bc3a1 137 valueBytes[8] = 0x00; // Fractions256
ohneta 0:8c79e11bc3a1 138 valueBytes[9] = 0x00; // Adjust Reason
ohneta 0:8c79e11bc3a1 139 }
ohneta 0:8c79e11bc3a1 140
ohneta 0:8c79e11bc3a1 141 /**
ohneta 0:8c79e11bc3a1 142 */
ohneta 0:8c79e11bc3a1 143 void readDateTime(BLE_DateTime &dateTime)
ohneta 0:8c79e11bc3a1 144 {
ohneta 0:8c79e11bc3a1 145 dateTime.year = (uint16_t)valueBytes[0] << 8 | valueBytes[1];
ohneta 0:8c79e11bc3a1 146 dateTime.month = valueBytes[2];
ohneta 0:8c79e11bc3a1 147 dateTime.day = valueBytes[3];
ohneta 0:8c79e11bc3a1 148 dateTime.hours = valueBytes[4];
ohneta 0:8c79e11bc3a1 149 dateTime.minutes = valueBytes[5];
ohneta 0:8c79e11bc3a1 150 dateTime.seconds = valueBytes[6];
ohneta 0:8c79e11bc3a1 151 }
ohneta 0:8c79e11bc3a1 152
ohneta 0:8c79e11bc3a1 153
ohneta 0:8c79e11bc3a1 154 // for BLE GATT callback
ohneta 0:8c79e11bc3a1 155 // "WRITE" is optionaly
ohneta 0:8c79e11bc3a1 156 virtual void onDataWritten(const GattWriteCallbackParams *params)
ohneta 0:8c79e11bc3a1 157 {
ohneta 0:8c79e11bc3a1 158 if (params->handle == currentTimeCharacteristic.getValueHandle()) {
ohneta 0:8c79e11bc3a1 159 memcpy((void *)&valueBytes, params->data, params->len);
ohneta 0:8c79e11bc3a1 160 }
ohneta 0:8c79e11bc3a1 161 }
ohneta 0:8c79e11bc3a1 162
ohneta 0:8c79e11bc3a1 163 protected:
ohneta 0:8c79e11bc3a1 164 BLE &ble;
ohneta 0:8c79e11bc3a1 165 uint8_t valueBytes[BLE_CURRENT_TIME_CHAR_VALUE_SIZE];
ohneta 0:8c79e11bc3a1 166 GattCharacteristic currentTimeCharacteristic;
ohneta 0:8c79e11bc3a1 167
ohneta 0:8c79e11bc3a1 168
ohneta 0:8c79e11bc3a1 169
ohneta 0:8c79e11bc3a1 170 /*
ohneta 0:8c79e11bc3a1 171 // for debug infos.
ohneta 0:8c79e11bc3a1 172 void printExactTime256Buffer()
ohneta 0:8c79e11bc3a1 173 {
ohneta 0:8c79e11bc3a1 174 BEL_CurrentTime currentTime;
ohneta 0:8c79e11bc3a1 175 currentTime.year = *((uint16_t *)&valueBytes[0]);
ohneta 0:8c79e11bc3a1 176 currentTime.month = valueBytes[2];
ohneta 0:8c79e11bc3a1 177 currentTime.day = valueBytes[3];
ohneta 0:8c79e11bc3a1 178 currentTime.hours = valueBytes[4];
ohneta 0:8c79e11bc3a1 179 currentTime.minutes = valueBytes[5];
ohneta 0:8c79e11bc3a1 180 currentTime.seconds = valueBytes[6];
ohneta 0:8c79e11bc3a1 181 currentTime.dayOfWeek = (BLE_DayofWeek)valueBytes[7];
ohneta 0:8c79e11bc3a1 182
ohneta 0:8c79e11bc3a1 183 pc.printf("%04d-%02d-%02d %02d:%02d:%02d [%02d]\n",
ohneta 0:8c79e11bc3a1 184 currentTime.year, currentTime.month, currentTime.day,
ohneta 0:8c79e11bc3a1 185 currentTime.hours, currentTime.minutes, currentTime.seconds,
ohneta 0:8c79e11bc3a1 186 currentTime.dayOfWeek );
ohneta 0:8c79e11bc3a1 187 }
ohneta 0:8c79e11bc3a1 188 */
ohneta 0:8c79e11bc3a1 189 };
ohneta 0:8c79e11bc3a1 190
ohneta 0:8c79e11bc3a1 191 #endif /* #ifndef __BLE_CURRENT_TIME_SERVICE_H__*/