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 24 08:53:24 2015 +0000
Revision:
5:2d2370b78f0e
Parent:
4:ad8739f7e30a
???????????????????

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