summaryrefslogtreecommitdiff
path: root/include/pio/libs/config/homekit
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2023-09-27 00:54:57 +0300
committerEvgeny Zinoviev <me@ch1p.io>2023-09-27 00:54:57 +0300
commitd3a295872c49defb55fc8e4e43e55550991e0927 (patch)
treeb9dca15454f9027d5a9dad0d4443a20de04dbc5d /include/pio/libs/config/homekit
parentb7cbc2571c1870b4582ead45277d0aa7f961bec8 (diff)
parentbdbb296697f55f4c3a07af43c9aaf7a9ea86f3d0 (diff)
Merge branch 'master' of ch1p.io:homekit
Diffstat (limited to 'include/pio/libs/config/homekit')
-rw-r--r--include/pio/libs/config/homekit/config.cpp84
-rw-r--r--include/pio/libs/config/homekit/config.h37
2 files changed, 121 insertions, 0 deletions
diff --git a/include/pio/libs/config/homekit/config.cpp b/include/pio/libs/config/homekit/config.cpp
new file mode 100644
index 0000000..5bafcad
--- /dev/null
+++ b/include/pio/libs/config/homekit/config.cpp
@@ -0,0 +1,84 @@
+#include <EEPROM.h>
+#include <strings.h>
+#include "config.h"
+#include <homekit/logging.h>
+
+#define GET_DATA_CRC(data) \
+ eeprom_crc(reinterpret_cast<uint8_t*>(&(data))+4, sizeof(ConfigData)-4)
+
+namespace homekit::config {
+
+static const uint32_t magic = 0xdeadbeef;
+static const uint32_t crc_table[16] PROGMEM = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+};
+
+static uint32_t eeprom_crc(const uint8_t* data, size_t len) {
+ uint32_t crc = ~0L;
+ for (size_t index = 0; index < len; index++) {
+ crc = pgm_read_word(&crc_table[(crc ^ data[index]) & 0x0f]) ^ (crc >> 4);
+ crc = pgm_read_word(&crc_table[(crc ^ (data[index] >> 4)) & 0x0f]) ^ (crc >> 4);
+ crc = ~crc;
+ }
+ return crc;
+}
+
+ConfigData read() {
+ ConfigData data;
+ EEPROM.begin(sizeof(ConfigData));
+ EEPROM.get(0, data);
+ EEPROM.end();
+#ifdef DEBUG
+ if (!isValid(data)) {
+ PRINTLN("config::read(): data is not valid!");
+ }
+#endif
+ return data;
+}
+
+void write(ConfigData& data) {
+ EEPROM.begin(sizeof(ConfigData));
+ data.magic = magic;
+ data.crc = GET_DATA_CRC(data);
+ EEPROM.put(0, data);
+ EEPROM.end();
+}
+
+void erase() {
+ ConfigData data;
+ erase(data);
+}
+
+void erase(ConfigData& data) {
+ bzero(reinterpret_cast<uint8_t*>(&data), sizeof(data));
+ write(data);
+}
+
+bool isValid(ConfigData& data) {
+ return data.crc == GET_DATA_CRC(data);
+}
+
+bool isDirty(ConfigData& data) {
+ return data.magic != magic;
+}
+
+char* ConfigData::escapeHomeId(char* buf, size_t len) {
+ if (len < 32)
+ return nullptr;
+ size_t id_len = strlen(node_id);
+ char* c = node_id;
+ char* dst = buf;
+ for (size_t i = 0; i < id_len; i++) {
+ if (*c == '"')
+ *(dst++) = '\\';
+ *(dst++) = *c;
+ c++;
+ }
+ *dst = '\0';
+ return buf;
+}
+
+}
diff --git a/include/pio/libs/config/homekit/config.h b/include/pio/libs/config/homekit/config.h
new file mode 100644
index 0000000..28f01fb
--- /dev/null
+++ b/include/pio/libs/config/homekit/config.h
@@ -0,0 +1,37 @@
+#ifndef COMMON_HOMEKIT_CONFIG_H
+#define COMMON_HOMEKIT_CONFIG_H
+
+#include <Arduino.h>
+
+namespace homekit::config {
+
+struct ConfigFlags {
+ uint8_t wifi_configured: 1;
+ uint8_t node_configured: 1;
+ uint8_t reserved: 6;
+} __attribute__((packed));
+
+struct ConfigData {
+ // helpers
+ uint32_t crc = 0;
+ uint32_t magic = 0;
+ char node_id[16] = {0};
+ char wifi_ssid[32] = {0};
+ char wifi_psk[63] = {0};
+ ConfigFlags flags {0};
+
+ // helper methods
+ char* escapeHomeId(char* buf, size_t len);
+} __attribute__((packed));
+
+
+ConfigData read();
+void write(ConfigData& data);
+void erase();
+void erase(ConfigData& data);
+bool isValid(ConfigData& data);
+bool isDirty(ConfigData& data);
+
+}
+
+#endif //COMMON_HOMEKIT_CONFIG_H \ No newline at end of file