summaryrefslogtreecommitdiff
path: root/src/ble.cpp
blob: 1e0b252aa2a41a5a388165f3033ae2174a52af08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "badge/ble.h"

#include <NimBLEDevice.h>

#include "badge/config.h"
#include "badge/log.h"

static NimBLEServer *server;
static NimBLEAdvertising *pAdvertising;
static NimBLECharacteristic *selectorCharacteristic;

#define IMAGE_DATA(_, display) display

const char *templates[] = {
#include "./images.cfg"
};

class BadgeServerCallbacks : public NimBLEServerCallbacks
{
    void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override
    {
        NimBLEServerCallbacks::onConnect(pServer, connInfo);
    }
    void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override
    {
        NimBLEServerCallbacks::onDisconnect(pServer, connInfo, reason);
    }
} badgeServerCallbacks;

class BadgeSelectorCallbacks : public NimBLECharacteristicCallbacks
{
    void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override
    {
        NimBLECharacteristicCallbacks::onWrite(pCharacteristic, connInfo);

        if (pCharacteristic == selectorCharacteristic)
        {
            const char *val = pCharacteristic->getValue().c_str();
            char *end = NULL;
            long newVal = strtol(val, &end, 10);
            if (end == NULL || end == val)
            {
                LOG_F("Error parsing value\n");
                pCharacteristic->setValue("0");
                pCharacteristic->notify(BLE_HS_CONN_HANDLE_NONE);
            }
            else if (newVal >= ARRAY_SIZE(templates))
            {
                LOG_F("Value out of range: %d\n", newVal);
                pCharacteristic->setValue("0");
                pCharacteristic->notify(BLE_HS_CONN_HANDLE_NONE);
            }
            else
            {
                LOG_F("Value set to %d\n", newVal);
            }
        }
    }
} badgeSelectorCallbacks;

void de::uvok::badge::ble_init(void)
{
    NimBLEDevice::init("Espadge");
    server = NimBLEDevice::createServer();
    server->setCallbacks(&badgeServerCallbacks);

    NimBLEService *service = new NimBLEService("ca260000-b4bb-46b2-bd06-b7b7a61ea990");
    // read/write current
    selectorCharacteristic =
        service->createCharacteristic("ca260001-b4bb-46b2-bd06-b7b7a61ea990",
                                      NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);
    selectorCharacteristic->setValue("0");
    selectorCharacteristic->setCallbacks(&badgeSelectorCallbacks);

    // get pictures
    auto call = service->createCharacteristic("ca260002-b4bb-46b2-bd06-b7b7a61ea990", NIMBLE_PROPERTY::READ);

    // needs to be on heap
    String *s = new String();
    for (int i = 0; i < ARRAY_SIZE(templates); i++)
    {
        char tmp[32];
        snprintf(tmp, sizeof(tmp), "%d-%s;", i, templates[i]);
        s->concat(tmp);
    }
    call->setValue(s->c_str());

    service->start();

    server->addService(service);

    pAdvertising = NimBLEDevice::getAdvertising();
    pAdvertising->setName("NimBLE");
}

void de::uvok::badge::ble_advertise(void)
{
    if (!pAdvertising->isAdvertising())
    {
        Serial.println("Long press detected. Starting advertising...");
        pAdvertising->start(10000);
    }
}