Merge branch 'main' into feature/type_8

This commit is contained in:
patman15
2024-12-29 12:49:44 +01:00
2 changed files with 844 additions and 175 deletions

View File

@@ -1,40 +1,58 @@
/** /**
* Emulate a Hunter Douglas PowerView cover device using ESP32 * Emulate a Hunter Douglas PowerView cover device using ESP32
* used e.g. to gain the home_key from an existing installation via BLE
* *
* TODO: * TODO:
* - adding device to appartement does only work after long timeout, * - cleanup code
* as some feedback to "reset scene automations" is expected * - think about emulating a remote
* *
* AUTHOR: patman15 * AUTHOR: patman15
* LICENSE: GPLv2 * LICENSE: GPLv2
*/ */
#define NAME "myPVcover"
#define FW_VERSION "391"
#define SERIAL_NR "01234567890ABCDEF"
#include <BLEDevice.h> #include <BLEDevice.h>
#include <BLEServer.h> #include <BLEServer.h>
#include <BLEUtils.h> #include <BLEUtils.h>
#include <BLE2902.h> #include <BLE2902.h>
#define WOLFSSL_USER_SETTINGS
#include <wolfssl.h>
#include "wolfssl/wolfcrypt/aes.h"
Aes aes_coder;
void *hint = NULL;
int devId = INVALID_DEVID; //if not using async INVALID_DEVID is default
#include <stdarg.h> #include <stdarg.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#define NAME "myPVcover"
#define COVER_SERVICE_UUID "0000FDC1-0000-1000-8000-00805f9b34fb" #define COVER_SERVICE_UUID "0000FDC1-0000-1000-8000-00805f9b34fb"
#define COVER_CHAR_UUID "CAFE1001-C0FF-EE01-8000-A110CA7AB1E0" #define COVER_CHAR_UUID "CAFE1001-C0FF-EE01-8000-A110CA7AB1E0"
#define XXX_CHAR_UUID "CAFE1002-C0FF-EE01-8000-A110CA7AB1E0" #define XXX_CHAR_UUID "CAFE1002-C0FF-EE01-8000-A110CA7AB1E0"
//#define FW_SERVICE_UUID "CAFE8000-C0FF-EE01-8000-A110CA7AB1E0" #define FW_SERVICE_UUID "CAFE8000-C0FF-EE01-8000-A110CA7AB1E0"
#define FW_CHAR_UUID "CAFE8003-C0FF-EE01-8000-A110CA7AB1E0"
#define DEV_SERVICE_UUID BLEUUID("180A")
#define SER_CHAR_UUID BLEUUID("2A25")
#define SWC_CHAR_UUID BLEUUID("2A28")
#define BAT_SERVICE_UUID BLEUUID("180F") #define BAT_SERVICE_UUID BLEUUID("180F")
#define BAT_CHAR_UUID BLEUUID("2A19") #define BAT_CHAR_UUID BLEUUID("2A19")
#define DAT_LEN 255
#pragma pack(1) #pragma pack(1)
struct header { struct message {
uint8_t serviceID; uint8_t serviceID;
uint8_t cmdID; uint8_t cmdID;
uint8_t sequence; uint8_t sequence;
uint8_t data_len; uint8_t data_len;
uint8_t data[DAT_LEN];
}; };
struct position { struct position {
@@ -46,126 +64,240 @@ struct position {
}; };
struct notification { struct notification {
uint8_t *data; uint8_t *data;
BLECharacteristic *characteristic; BLECharacteristic *characteristic;
}; };
BLECharacteristic *pCharacteristic_cover, *pCharacteristic_fw, *pCharacteristic_unknown, *pCharacteristic_bat; BLECharacteristic *pCharacteristic_cover, *pCharacteristic_fw, *pCharacteristic_unknown, *pCharacteristic_bat;
BLECharacteristic *pCharacteristic_dev, *pCharacteristic_ser;
BLEServer *pServer = NULL; BLEServer *pServer = NULL;
bool deviceConnected = false; bool deviceConnected = false;
bool oldDeviceConnected = false; bool oldDeviceConnected = false;
struct notification rx_data; struct notification rx_data;
volatile bool data_available = false; volatile bool data_available = false;
uint8_t buffer[20]; const byte zero_key[16] = { 0 };
byte home_key[16] = { 0 };
const char* dec_cmd(uint16_t cmd) {
switch(cmd) {
case 0x01:
return "set position";
case 0xBA:
return "activate scene";
default:
return "ERR";
}
} const char *BLEstate[] = {
"SUCCESS_INDICATE",
void print_hex(uint8_t *value, uint8_t len) { "SUCCESS_NOTIFY",
for (int i = 0; i < len; i++) { "ERROR_INDICATE_DISABLED",
Serial.print("0x"); "ERROR_NOTIFY_DISABLED",
Serial.print(value[i], HEX); "ERROR_GATT",
Serial.print(" "); "ERROR_NO_CLIENT",
} "ERROR_INDICATE_TIMEOUT",
Serial.println(""); "ERROR_INDICATE_FAILURE"
}
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.print("connect ID: ");
Serial.println(pServer->getConnId());
/*pServer->updatePeerMTU(pServer->getConnId(), 310);
Serial.print("MTU: ");
Serial.println(pServer->getPeerMTU(pServer->getConnId()));*/
deviceConnected = true;
BLEDevice::startAdvertising();
};
void onDisconnect(BLEServer* pServer) {
Serial.println("disconnect.");
deviceConnected = false;
}
void onMtuChanged(BLEServer* pServer, esp_ble_gatts_cb_param_t* param) {
Serial.printf("MTU changed: %d\n", pServer->getPeerMTU(pServer->getConnId()));
}
}; };
void decode() { void print_hex(const uint8_t *value, uint8_t len, const char *prefix = "0x", const char *postfix = " ") {
Serial.printf("Cover write %s:\n\t", rx_data.characteristic->toString().c_str()); for (int i = 0; i < len; i++) {
print_hex(rx_data.characteristic->getData(), rx_data.characteristic->getLength()); Serial.printf("%s%02X%s", prefix, value[i], postfix);
}
if (rx_data.characteristic->getLength() < 4) return; Serial.println();
struct header data;
memcpy((void *) &data, rx_data.characteristic->getData(), 4);
Serial.printf("SRV: %x, CMD %x, SEQ %x, LEN %x\n", data.serviceID, data.cmdID, data.sequence, data.data_len);
switch ((data.serviceID << 8) | data.cmdID) {
case 0xF701:
// set position
struct position pos;
memcpy((void *) &pos, &rx_data.data[4], data.data_len);
Serial.printf("\tset position\tpos1 %f%%, pos2 %d, pos3 %d, tilt %d, velocity %d\n", pos.pos1/100.0, pos.pos2, pos.pos3, pos.tilt, pos.velocity);
break;
case 0xF7B8:
// stop movement
Serial.println("\tstop");
break;
case 0xF7BA:
// activate scene
Serial.printf("\tactivate scene\tscene #%d\n", (uint16_t) rx_data.data[4]);
break;
case 0xFA5B:
// get scene
Serial.printf("\tget scene\tscene #%d\n", (uint16_t) rx_data.data[4]);
break;
case 0xFAEA:
// Reset Scene Automations
// FIXME! wrong return value!
const uint8_t ret_val[] = {0xEA, 0xEA, data.sequence, 0x1, 0x0};
Serial.println("\treset scene automations:");
memcpy(&buffer, ret_val, 5);
delay(100);
Serial.print("\t\tret value: ");
print_hex(buffer, 5);
rx_data.characteristic->setValue((uint8_t *) &buffer, 5);
rx_data.characteristic->notify();
break;
}
Serial.println();
} }
class coverCallbacks: public BLECharacteristicCallbacks { uint8_t set_response(message *response, const message *request, const byte *data = NULL, const uint8_t data_len = 1) {
const uint8_t message_len = min(data_len, (uint8_t)DAT_LEN) + sizeof(struct message) - DAT_LEN;
response->serviceID = request->serviceID & 0xEF;
response->cmdID = request->cmdID;
response->sequence = request->sequence;
response->data_len = min(data_len, (uint8_t)DAT_LEN);
if (data) {
memcpy(response->data, data, std::min(data_len, (uint8_t)DAT_LEN));
} else {
*response->data = 0x0;
}
Serial.printf("\tret value (%i): ", message_len);
print_hex((const uint8_t *)response, message_len);
if (memcmp(home_key, zero_key, sizeof(zero_key))) {
message unencrypted;
memcpy(&unencrypted, response, message_len);
// AES counter is reset every message, so we need to init it each time
if (wc_AesInit(&aes_coder, hint, devId) || wc_AesSetKey(&aes_coder, (const byte *)home_key, 16, zero_key, AES_ENCRYPTION)) {
Serial.println("FATAL: setting AES init failed!");
return 0;
}
if (wc_AesCtrEncrypt(&aes_coder, (byte *)response, (const byte *)&unencrypted, message_len)) {
Serial.println(F("FATAL: encryption failed!"));
return 0;
}
Serial.printf("\tencrypted (%i): ", message_len);
print_hex((const uint8_t *)response, message_len);
}
return message_len;
}
void decode(BLECharacteristic *pChar) {
message response;
byte data_dec[DAT_LEN];
const uint16_t data_len = pChar->getLength();
const byte *data_raw = pChar->getData();
struct message msg;
uint8_t resp_size = 0;
Serial.print("\t BLE data: ");
print_hex(data_raw, data_len);
if (data_len < 4) return;
if (memcmp(home_key, zero_key, sizeof(zero_key))) {
if (wc_AesInit(&aes_coder, hint, devId) || wc_AesSetKey(&aes_coder, (const byte *)home_key, 16, zero_key, AES_ENCRYPTION)) {
Serial.println("FATAL: setting AES init failed!");
}
if (wc_AesCtrEncrypt(&aes_coder, data_dec, data_raw, data_len)) {
Serial.println(F("FATAL: decryption failed!"));
return;
}
Serial.print("\tdecrypted: ");
print_hex(data_dec, data_len);
} else {
memcpy(data_dec, data_raw, data_len);
}
memcpy((void *)&msg, data_dec, 4);
Serial.printf("\t message: SRV: %02x, CMD %02x, SEQ %i, LEN %i\n", msg.serviceID, msg.cmdID, msg.sequence, msg.data_len);
// sepecial responses (static data!)
const byte ret_valF1DD[] = { 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // product info
const byte ret_valFFDD[] = { 0x00, 0x05, 0xd1, 0xa2, 0x9a, 0x42, 0x59, 0x5d, 0x5c, 0x52, 0x1b, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00, 0x5f, 0x9c, 0x02, 0x00, 0x5f, 0x9c, 0x02, 0x00, 0x2a, 0xe0, 0x08 }; // HW diagnostics
const byte ret_valFFDE[] = { 0x08, 0x00, 0x02, 0x26, 0x72, 0x01, 0x59, 0x01, 0x00 }; // power status
const byte ret_valFA5B[] = { 0x00, 0x0a, 0xa2, 0x88, 0x13, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // get scene
const byte ret_valFA5A[] = { 0x00, 0x02, 0xb0 }; // set scene
Serial.print("\t\t");
switch ((msg.serviceID << 8) | msg.cmdID) {
case 0xF1DD:
Serial.println("get product info.");
resp_size = set_response(&response, (const message *)data_dec, ret_valF1DD, sizeof(ret_valF1DD));
break;
case 0xF701:
// set position
struct position pos;
memcpy((void *)&pos, &data_dec[4], msg.data_len);
Serial.printf("set position: pos1 %f%%, pos2 %d, pos3 %d, tilt %d, velocity %d\n", pos.pos1 / 100.0, pos.pos2, pos.pos3, pos.tilt, pos.velocity);
break;
case 0xF711:
// identify
Serial.printf("identify: %i\n", data_dec[4]);
resp_size = set_response(&response, (const message *)data_dec);
break;
case 0xF7B8:
// stop movement
Serial.println("stop.");
break;
case 0xF7BA:
// activate scene
Serial.printf("activate scene #%i\n", data_dec[4]);
break;
case 0xFA5A:
// set scene
Serial.printf("set scene #%i\n", data_dec[4]);
resp_size = set_response(&response, (const message *)data_dec, ret_valFA5A, sizeof(ret_valFA5A));
break;
case 0xFA5B:
// get scene
Serial.printf("get scene #%i\n", data_dec[4]);
resp_size = set_response(&response, (const message *)data_dec, ret_valFA5B, sizeof(ret_valFA5B));
break;
case 0xFAEA:
// Reset Scene Automations
Serial.println("reset scene automations:");
resp_size = set_response(&response, (const message *)data_dec);
break;
case 0xFB02:
// set shade key
Serial.print("set shade key: ");
print_hex(&data_raw[4], data_len - 4, "\\x");
// set resonse before key, to acknowledge unencrypted
resp_size = set_response(&response, (const message *)data_dec);
if (msg.data_len == 16) {
memcpy(home_key, &data_raw[4], 16);
}
break;
// case 0xFF67:
// // get shade time
// break;
case 0xFF77:
// set shade time
Serial.printf("set time: %i-%i-%i %i:%i:%i\n", data_dec[4] | data_dec[5] << 8, data_dec[6], data_dec[7], data_dec[8], data_dec[9], data_dec[10]);
resp_size = set_response(&response, (const message *)data_dec);
break;
case 0xFF87:
Serial.printf("set sunrise %i:%i:%i, sunset %i:%i:%i\n", data_dec[4], data_dec[5], data_dec[6], data_dec[7], data_dec[8], data_dec[9]);
resp_size = set_response(&response, (const message *)data_dec);
break;
case 0xFFD7:
Serial.printf("set shade configuration: 0x%02X, status LED: %s\n", data_dec[4], data_dec[5] ? "on" : "off");
resp_size = set_response(&response, (const message *)data_dec);
break;
case 0xFFDD:
// get HW diagnostics
Serial.println("get HW diagnostics.");
resp_size = set_response(&response, (const message *)data_dec, ret_valFFDD, sizeof(ret_valFFDD));
break;
case 0xFFDE:
// get power status
Serial.println("get power status.");
resp_size = set_response(&response, (const message *)&data_dec, ret_valFFDE, sizeof(ret_valFFDE));
break;
case 0xFFDF:
// set power type
Serial.printf("set power type: %i\n", data_dec[4]);
resp_size = set_response(&response, (const message *)data_dec);
break;
case 0xFFEE:
Serial.println("factory reset.");
resp_size = set_response(&response, (const message *)data_dec);
break;
default:
Serial.println(F("*********************************** unknown message"));
}
if (resp_size) {
pChar->setValue((uint8_t *)&response, resp_size);
pChar->notify();
}
}
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *pServer) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.printf("connect ID: %i\n", pServer->getConnId());
deviceConnected = true;
BLEDevice::startAdvertising();
};
void onDisconnect(BLEServer *pServer) {
digitalWrite(LED_BUILTIN, LOW);
Serial.printf("disconnect ID: %i\n\n", pServer->getConnId());
deviceConnected = false;
}
void onMtuChanged(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) {
Serial.printf("MTU changed: %d\n", pServer->getPeerMTU(pServer->getConnId()));
}
};
class coverCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) { void onWrite(BLECharacteristic *pCharacteristic) {
rx_data.characteristic = pCharacteristic; Serial.printf("Cover write %s\n", pCharacteristic->toString().c_str());
data_available = true; decode(pCharacteristic);
} }
void onRead(BLECharacteristic *pCharacteristic) { void onRead(BLECharacteristic *pCharacteristic) {
Serial.printf("Cover read: %s\n", pCharacteristic->toString().c_str()); Serial.printf("Cover read: %s\n", pCharacteristic->toString().c_str());
} }
void onNotify(BLECharacteristic *pCharacteristic){ void onNotify(BLECharacteristic *pCharacteristic) {
Serial.println("onNotify()"); Serial.printf("Cover onNotify() %s\n", pCharacteristic->toString().c_str());
} // not used }
void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code){
Serial.println("onStatus()");
}; // not used
void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code) {
Serial.printf("Cover onStatus() %s: %s\n", BLEstate[s], pCharacteristic->toString().c_str());
}
}; };
class batteryCallbacks: public BLECharacteristicCallbacks { class batteryCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) { void onWrite(BLECharacteristic *pCharacteristic) {
uint8_t *value = pCharacteristic->getData(); uint8_t *value = pCharacteristic->getData();
@@ -176,36 +308,35 @@ class batteryCallbacks: public BLECharacteristicCallbacks {
} }
void onRead(BLECharacteristic *pCharacteristic) { void onRead(BLECharacteristic *pCharacteristic) {
Serial.printf("Battery read: %s\n", pCharacteristic->toString().c_str()); Serial.printf("Battery read: %s\n", pCharacteristic->toString().c_str());
} }
void onNotify(BLECharacteristic *pCharacteristic){ void onNotify(BLECharacteristic *pCharacteristic) {
Serial.println("Battery onNotify()"); Serial.println("Battery onNotify()");
} // not used }
void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code){ void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code) {
Serial.println("Battery onStatus()"); Serial.println("Battery onStatus()");
}; // not used }
}; };
class genericCallbacks: public BLECharacteristicCallbacks { class genericCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) { void onWrite(BLECharacteristic *pCharacteristic) {
//uint8_t *value = pCharacteristic->getData(); //uint8_t *value = pCharacteristic->getData();
Serial.printf("generic write %s:", pCharacteristic->toString().c_str()); Serial.printf("generic write %s:\n", pCharacteristic->toString().c_str());
//print_hex(value, pCharacteristic->getLength()); //print_hex(value, pCharacteristic->getLength());
Serial.println();
} }
void onRead(BLECharacteristic *pCharacteristic) { void onRead(BLECharacteristic *pCharacteristic) {
Serial.printf("generic read %s.\n", pCharacteristic->toString().c_str()); Serial.printf("generic read %s.\n", pCharacteristic->toString().c_str());
} }
void onNotify(BLECharacteristic *pCharacteristic){ void onNotify(BLECharacteristic *pCharacteristic) {
Serial.println("generic onNotify()"); Serial.printf("generic onNotify() %s\n", pCharacteristic->toString().c_str());
} // not used } // not used
void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code){ void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code) {
Serial.println("generic onStatus()"); Serial.printf("generic onStatus() %s - %s\n", BLEstate[s], pCharacteristic->toString().c_str());
}; // not used }; // not used
}; };
void setup() { void setup() {
@@ -221,68 +352,71 @@ void setup() {
BLEService *pCovService = pServer->createService(COVER_SERVICE_UUID); BLEService *pCovService = pServer->createService(COVER_SERVICE_UUID);
// Create a BLE Characteristic // Create a BLE Characteristic
pCharacteristic_cover = pCovService->createCharacteristic( pCharacteristic_cover = pCovService->createCharacteristic(
COVER_CHAR_UUID, COVER_CHAR_UUID,
BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_WRITE_NR
);
pCharacteristic_cover->setCallbacks(new coverCallbacks()); pCharacteristic_cover->setCallbacks(new coverCallbacks());
// Create a BLE Descriptor // Create a BLE Descriptor
/* BLEDescriptor *pDesc1 = new BLEDescriptor("2901", 10); /* BLEDescriptor *pDesc1 = new BLEDescriptor("2901", 10);
pDesc1->setValue("cover");*/ pDesc1->setValue("cover");*/
//pCharacteristic_cover->addDescriptor(pDesc1); //pCharacteristic_cover->addDescriptor(pDesc1);
pCharacteristic_cover->addDescriptor(new BLE2902()); pCharacteristic_cover->addDescriptor(new BLE2902());
pCharacteristic_unknown = pCovService->createCharacteristic( pCharacteristic_unknown = pCovService->createCharacteristic(
XXX_CHAR_UUID, XXX_CHAR_UUID,
BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_WRITE_NR
);
pCharacteristic_unknown->setCallbacks(new genericCallbacks()); pCharacteristic_unknown->setCallbacks(new genericCallbacks());
pCharacteristic_unknown->addDescriptor(new BLE2902()); pCharacteristic_unknown->addDescriptor(new BLE2902());
// BLEService *pBatService = pServer->createService(BAT_SERVICE_UUID); BLEService *pBatService = pServer->createService(BAT_SERVICE_UUID);
pCharacteristic_bat = pBatService->createCharacteristic(
BAT_CHAR_UUID,
BLECharacteristic::PROPERTY_READ);
pCharacteristic_bat->setCallbacks(new batteryCallbacks());
uint8_t battery_level = 42;
pCharacteristic_bat->setValue(&battery_level, 1);
pCharacteristic_bat->addDescriptor(new BLE2902());
// pCharacteristic_bat = pBatService->createCharacteristic( BLEService *pFWService = pServer->createService(FW_SERVICE_UUID);
// BAT_CHAR_UUID, pCharacteristic_fw = pFWService->createCharacteristic(
// BLECharacteristic::PROPERTY_READ FW_CHAR_UUID,
// ); BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
// pCharacteristic_bat->setCallbacks(new batteryCallbacks()); pCharacteristic_fw->setCallbacks(new genericCallbacks());
// uint8_t battery_level = 42; pCharacteristic_fw->addDescriptor(new BLE2902());
// pCharacteristic_bat->setValue(&battery_level, 1); BLEDescriptor *pDesc2 = new BLEDescriptor("2901", 10);
// pCharacteristic_bat->addDescriptor(new BLE2902()); pDesc2->setValue("firmware");
pCharacteristic_fw->addDescriptor(pDesc2);
// BLEService *pFWService = pServer->createService(FW_SERVICE_UUID);
// pCharacteristic_fw = pCovService->createCharacteristic(
// CHAR_FW_UUID,
// BLECharacteristic::PROPERTY_READ |
// BLECharacteristic::PROPERTY_WRITE |
// BLECharacteristic::PROPERTY_WRITE_NR
// );
// pCharacteristic_fw->setCallbacks(new genericCallbacks());
// pCharacteristic_fw->addDescriptor(new BLE2902());
// pCharacteristic_fw->addDescriptor(pDesc2);
//BLEDescriptor *pDesc2 = new BLEDescriptor("2901", 10);
//pDesc2->setValue("firmware");
// Start the service BLEService *pDEVService = pServer->createService(DEV_SERVICE_UUID);
pCharacteristic_dev = pDEVService->createCharacteristic(
SWC_CHAR_UUID,
BLECharacteristic::PROPERTY_READ);
pCharacteristic_dev->setValue(FW_VERSION);
pCharacteristic_dev->setCallbacks(new genericCallbacks());
pCharacteristic_ser = pDEVService->createCharacteristic(
SER_CHAR_UUID,
BLECharacteristic::PROPERTY_READ);
pCharacteristic_ser->setValue(SERIAL_NR);
pCharacteristic_ser->setCallbacks(new genericCallbacks());
// Start the services
pCovService->start(); pCovService->start();
//pFWService->start(); pFWService->start();
pBatService->start();
pDEVService->start();
// Start advertising // Start advertising
BLEAdvertisementData AdvertisementData; BLEAdvertisementData AdvertisementData;
const String manufacturerData = String("\x19\x08\x00\x00\x2A\x00\x00\x00\x00\x00\xA2",11); const String manufacturerData = String("\x19\x08\x00\x00\x2A\x00\x00\x00\x00\x00\xA2", 11);
// Hunter Douglas ^^--^^ ^^ ID-Type // Hunter Douglas ^^--^^ ^^key^^ ^^ ID-Type
AdvertisementData.setManufacturerData(manufacturerData); AdvertisementData.setManufacturerData(manufacturerData);
AdvertisementData.setPartialServices(BLEUUID(COVER_SERVICE_UUID)); AdvertisementData.setPartialServices(BLEUUID(COVER_SERVICE_UUID));
AdvertisementData.setFlags((1 << 2) | (1 << 1)); // [BR/EDR Not Supported] | [LE General Discoverable Mode] AdvertisementData.setFlags((1 << 2) | (1 << 1)); // [BR/EDR Not Supported] | [LE General Discoverable Mode]
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->setAdvertisementData(AdvertisementData); pAdvertising->setAdvertisementData(AdvertisementData);
BLEDevice::startAdvertising(); BLEDevice::startAdvertising();
Serial.println("Device " NAME " ready."); Serial.println("Device " NAME " ready.");
@@ -302,9 +436,4 @@ void loop() {
// do stuff here on connecting // do stuff here on connecting
oldDeviceConnected = deviceConnected; oldDeviceConnected = deviceConnected;
} }
if (deviceConnected && data_available) {
data_available = false;
decode();
delay(100);
}
} }

View File

@@ -0,0 +1,540 @@
/* user_settings_template.h
*
* Copyright (C) 2006-2024 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* Example wolfSSL user settings with #if 0/1 gates to enable/disable algorithms and features.
* This file is included with wolfssl/wolfcrypt/settings.h when WOLFSSL_USER_SETTINGS is defined.
* Based on IDE/GCC-ARM/Headers/user_settings.h
*/
#ifndef WOLFSSL_USER_SETTINGS_H
#define WOLFSSL_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
/* If TARGET_EMBEDDED is defined then small target settings are used */
#if !(defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__) || defined(_WIN32))
#define TARGET_EMBEDDED
#endif
/* ------------------------------------------------------------------------- */
/* Platform */
/* ------------------------------------------------------------------------- */
#define WOLFSSL_GENERAL_ALIGNMENT 4
#define SIZEOF_LONG_LONG 8
#if 0
#define NO_64BIT /* disable use of 64-bit variables */
#endif
#ifdef TARGET_EMBEDDED
/* disable mutex locking */
#define SINGLE_THREADED
/* reduce stack use. For variables over 100 bytes allocate from heap */
#define WOLFSSL_SMALL_STACK
/* Disable the built-in socket support and use the IO callbacks.
* Set IO callbacks with wolfSSL_CTX_SetIORecv/wolfSSL_CTX_SetIOSend
*/
#define WOLFSSL_USER_IO
#endif
/* ------------------------------------------------------------------------- */
/* Math Configuration */
/* ------------------------------------------------------------------------- */
/* Wolf Single Precision Math */
#if 1
#define WOLFSSL_HAVE_SP_RSA
#define WOLFSSL_HAVE_SP_DH
#define WOLFSSL_HAVE_SP_ECC
//#define WOLFSSL_SP_4096 /* Enable RSA/RH 4096-bit support */
//#define WOLFSSL_SP_384 /* Enable ECC 384-bit SECP384R1 support */
//#define WOLFSSL_SP_MATH /* only SP math - disables integer.c/tfm.c */
#define WOLFSSL_SP_MATH_ALL /* use SP math for all key sizes and curves */
//#define WOLFSSL_SP_NO_MALLOC
//#define WOLFSSL_SP_DIV_32 /* do not use 64-bit divides */
#ifdef TARGET_EMBEDDED
/* use smaller version of code */
#define WOLFSSL_SP_SMALL
#else
/* SP Assembly Speedups - specific to chip type */
#define WOLFSSL_SP_ASM
#endif
//#define WOLFSSL_SP_X86_64
//#define WOLFSSL_SP_X86
//#define WOLFSSL_SP_ARM32_ASM
//#define WOLFSSL_SP_ARM64_ASM
//#define WOLFSSL_SP_ARM_THUMB_ASM
//#define WOLFSSL_SP_ARM_CORTEX_M_ASM
#elif 1
/* Fast Math (tfm.c) (stack based and timing resistant) */
#define USE_FAST_MATH
#define TFM_TIMING_RESISTANT
#else
/* Normal (integer.c) (heap based, not timing resistant) - not recommended*/
#define USE_INTEGER_HEAP_MATH
#endif
/* ------------------------------------------------------------------------- */
/* Crypto */
/* ------------------------------------------------------------------------- */
/* RSA */
#undef NO_RSA
#if 0
#ifdef USE_FAST_MATH
/* Maximum math bits (Max RSA key bits * 2) */
#define FP_MAX_BITS 4096
#endif
/* half as much memory but twice as slow */
//#define RSA_LOW_MEM
/* Enables blinding mode, to prevent timing attacks */
#define WC_RSA_BLINDING
/* RSA PSS Support */
#define WC_RSA_PSS
#else
#define NO_RSA
#endif
/* DH */
#undef NO_DH
#if 0
/* Use table for DH instead of -lm (math) lib dependency */
#if 1
#define WOLFSSL_DH_CONST
#define HAVE_FFDHE_2048
//#define HAVE_FFDHE_4096
//#define HAVE_FFDHE_6144
//#define HAVE_FFDHE_8192
#endif
#else
#define NO_DH
#endif
/* ECC */
#undef HAVE_ECC
#if 0
#define HAVE_ECC
/* Manually define enabled curves */
#define ECC_USER_CURVES
#ifdef ECC_USER_CURVES
/* Manual Curve Selection */
//#define HAVE_ECC192
//#define HAVE_ECC224
#undef NO_ECC256
//#define HAVE_ECC384
//#define HAVE_ECC521
#endif
/* Fixed point cache (speeds repeated operations against same private key) */
//#define FP_ECC
#ifdef FP_ECC
/* Bits / Entries */
#define FP_ENTRIES 2
#define FP_LUT 4
#endif
/* Optional ECC calculation method */
/* Note: doubles heap usage, but slightly faster */
#define ECC_SHAMIR
/* Reduces heap usage, but slower */
#define ECC_TIMING_RESISTANT
/* Compressed ECC Key Support */
//#define HAVE_COMP_KEY
/* Use alternate ECC size for ECC math */
#ifdef USE_FAST_MATH
/* MAX ECC BITS = ROUND8(MAX ECC) * 2 */
#if defined(NO_RSA) && defined(NO_DH)
/* Custom fastmath size if not using RSA/DH */
#define FP_MAX_BITS (256 * 2)
#else
/* use heap allocation for ECC points */
#define ALT_ECC_SIZE
/* wolfSSL will compute the FP_MAX_BITS_ECC, but it can be overridden */
//#define FP_MAX_BITS_ECC (256 * 2)
#endif
/* Speedups specific to curve */
#ifndef NO_ECC256
#define TFM_ECC256
#endif
#endif
#endif
/* AES */
#undef NO_AES
#if 1
#define HAVE_AES_CBC
/* GCM Method: GCM_TABLE_4BIT, GCM_SMALL, GCM_WORD32 or GCM_TABLE */
#define HAVE_AESGCM
#ifdef TARGET_EMBEDDED
#define GCM_SMALL
#else
#define GCM_TABLE_4BIT
#endif
#define WOLFSSL_AES_DIRECT
//#define HAVE_AES_ECB
#define WOLFSSL_AES_COUNTER
//#define HAVE_AESCCM
#else
#define NO_AES
#endif
/* DES3 */
#undef NO_DES3
#if 0
#else
#define NO_DES3
#endif
/* ChaCha20 / Poly1305 */
#undef HAVE_CHACHA
#undef HAVE_POLY1305
#if 0
#define HAVE_CHACHA
#define HAVE_POLY1305
/* Needed for Poly1305 */
#define HAVE_ONE_TIME_AUTH
#endif
/* Ed25519 / Curve25519 */
#undef HAVE_CURVE25519
#undef HAVE_ED25519
#if 0
#define HAVE_CURVE25519
#define HAVE_ED25519 /* ED25519 Requires SHA512 */
/* Optionally use small math (less flash usage, but much slower) */
#if 1
#define CURVED25519_SMALL
#endif
#endif
/* ------------------------------------------------------------------------- */
/* Hashing */
/* ------------------------------------------------------------------------- */
/* Sha */
#undef NO_SHA
#if 1
/* 1k smaller, but 25% slower */
//#define USE_SLOW_SHA
#else
#define NO_SHA
#endif
/* Sha256 */
#undef NO_SHA256
#if 1
/* not unrolled - ~2k smaller and ~25% slower */
//#define USE_SLOW_SHA256
/* Sha224 */
#if 0
#define WOLFSSL_SHA224
#endif
#else
#define NO_SHA256
#endif
/* Sha512 */
#undef WOLFSSL_SHA512
#if 0
#define WOLFSSL_SHA512
/* Sha384 */
#undef WOLFSSL_SHA384
#if 0
#define WOLFSSL_SHA384
#endif
/* over twice as small, but 50% slower */
//#define USE_SLOW_SHA512
#endif
/* Sha3 */
#undef WOLFSSL_SHA3
#if 0
#define WOLFSSL_SHA3
#endif
/* MD5 */
#undef NO_MD5
#if 0
#else
#define NO_MD5
#endif
/* HKDF */
#undef HAVE_HKDF
#if 0
#define HAVE_HKDF
#endif
/* CMAC */
#undef WOLFSSL_CMAC
#if 0
#define WOLFSSL_CMAC
#endif
/* ------------------------------------------------------------------------- */
/* Benchmark / Test */
/* ------------------------------------------------------------------------- */
#ifdef TARGET_EMBEDDED
/* Use reduced benchmark / test sizes */
#define BENCH_EMBEDDED
#endif
/* Use test buffers from array (not filesystem) */
#ifndef NO_FILESYSTEM
#define USE_CERT_BUFFERS_256
#define USE_CERT_BUFFERS_2048
#endif
/* ------------------------------------------------------------------------- */
/* Debugging */
/* ------------------------------------------------------------------------- */
#undef DEBUG_WOLFSSL
#undef NO_ERROR_STRINGS
#if 0
#define DEBUG_WOLFSSL
#else
#if 0
#define NO_ERROR_STRINGS
#endif
#endif
/* ------------------------------------------------------------------------- */
/* Memory */
/* ------------------------------------------------------------------------- */
/* Override Memory API's */
#if 0
#define XMALLOC_OVERRIDE
/* prototypes for user heap override functions */
/* Note: Realloc only required for normal math */
/* Note2: XFREE(NULL) must be properly handled */
#include <stddef.h> /* for size_t */
extern void *myMalloc(size_t n, void* heap, int type);
extern void myFree(void *p, void* heap, int type);
extern void *myRealloc(void *p, size_t n, void* heap, int type);
#define XMALLOC(n, h, t) myMalloc(n, h, t)
#define XFREE(p, h, t) myFree(p, h, t)
#define XREALLOC(p, n, h, t) myRealloc(p, n, h, t)
#endif
#if 0
/* Static memory requires fast math */
#define WOLFSSL_STATIC_MEMORY
/* Disable fallback malloc/free */
#define WOLFSSL_NO_MALLOC
#if 1
#define WOLFSSL_MALLOC_CHECK /* trap malloc failure */
#endif
#endif
/* Memory callbacks */
#if 0
#undef USE_WOLFSSL_MEMORY
#define USE_WOLFSSL_MEMORY
/* Use this to measure / print heap usage */
#if 0
#define WOLFSSL_TRACK_MEMORY
#define WOLFSSL_DEBUG_MEMORY
#endif
#else
#ifndef WOLFSSL_STATIC_MEMORY
#define NO_WOLFSSL_MEMORY
/* Otherwise we will use stdlib malloc, free and realloc */
#endif
#endif
/* ------------------------------------------------------------------------- */
/* Port */
/* ------------------------------------------------------------------------- */
/* Override Current Time */
#if 0
/* Allows custom "custom_time()" function to be used for benchmark */
#define WOLFSSL_USER_CURRTIME
#define WOLFSSL_GMTIME
#define USER_TICKS
extern unsigned long my_time(unsigned long* timer);
#define XTIME my_time
#endif
/* ------------------------------------------------------------------------- */
/* RNG */
/* ------------------------------------------------------------------------- */
/* Choose RNG method */
#if 0
/* Custom Seed Source */
#if 0
/* Size of returned HW RNG value */
#define CUSTOM_RAND_TYPE unsigned int
extern unsigned int my_rng_seed_gen(void);
#undef CUSTOM_RAND_GENERATE
#define CUSTOM_RAND_GENERATE my_rng_seed_gen
#endif
/* Use built-in P-RNG (SHA256 based) with HW RNG */
/* P-RNG + HW RNG (P-RNG is ~8K) */
#undef HAVE_HASHDRBG
#define HAVE_HASHDRBG
#else
#undef WC_NO_HASHDRBG
#define WC_NO_HASHDRBG
/* Bypass P-RNG and use only HW RNG */
extern int my_rng_gen_block(unsigned char* output, unsigned int sz);
#undef CUSTOM_RAND_GENERATE_BLOCK
#define CUSTOM_RAND_GENERATE_BLOCK my_rng_gen_block
#endif
/* ------------------------------------------------------------------------- */
/* Custom Standard Lib */
/* ------------------------------------------------------------------------- */
/* Allows override of all standard library functions */
#undef STRING_USER
#if 0
#define STRING_USER
#include <string.h>
#define USE_WOLF_STRSEP
#define XSTRSEP(s1,d) wc_strsep((s1),(d))
#define USE_WOLF_STRTOK
#define XSTRTOK(s1,d,ptr) wc_strtok((s1),(d),(ptr))
#define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n))
#define XMEMCPY(d,s,l) memcpy((d),(s),(l))
#define XMEMSET(b,c,l) memset((b),(c),(l))
#define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n))
#define XMEMMOVE(d,s,l) memmove((d),(s),(l))
#define XSTRLEN(s1) strlen((s1))
#define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
#define XSTRSTR(s1,s2) strstr((s1),(s2))
#define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n))
#define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n))
#define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#define XSNPRINTF snprintf
#endif
/* ------------------------------------------------------------------------- */
/* Enable Features */
/* ------------------------------------------------------------------------- */
#define WOLFSSL_TLS13
#define WOLFSSL_OLD_PRIME_CHECK /* Use faster DH prime checking */
#define HAVE_TLS_EXTENSIONS
#define HAVE_SUPPORTED_CURVES
#define WOLFSSL_BASE64_ENCODE
//#define WOLFSSL_KEY_GEN /* For RSA Key gen only */
//#define KEEP_PEER_CERT
//#define HAVE_COMP_KEY
/* TLS Session Cache */
#if 0
#define SMALL_SESSION_CACHE
#else
#define NO_SESSION_CACHE
#endif
/* ------------------------------------------------------------------------- */
/* Disable Features */
/* ------------------------------------------------------------------------- */
#define NO_WOLFSSL_SERVER
#define NO_WOLFSSL_CLIENT
//#define NO_CRYPT_TEST
//#define NO_CRYPT_BENCHMARK
#define WOLFCRYPT_ONLY
/* do not warm when file is included to be built and not required to be */
#define WOLFSSL_IGNORE_FILE_WARN
/* In-lining of misc.c functions */
/* If defined, must include wolfcrypt/src/misc.c in build */
/* Slower, but about 1k smaller */
//#define NO_INLINE
#ifdef TARGET_EMBEDDED
#define NO_FILESYSTEM
#define NO_WRITEV
#define NO_MAIN_DRIVER
#define NO_DEV_RANDOM
#endif
#define NO_OLD_TLS
#define NO_PSK
#define NO_DSA
#define NO_RC4
#define NO_MD4
#define NO_PWDBASED
//#define NO_CODING
//#define NO_ASN_TIME
//#define NO_CERTS
//#define NO_SIG_WRAPPER
#ifdef __cplusplus
}
#endif
#endif /* WOLFSSL_USER_SETTINGS_H */