Skip to content

Commit be5e4bc

Browse files
Improved configuration
1 parent 28e0d3f commit be5e4bc

File tree

8 files changed

+468
-65
lines changed

8 files changed

+468
-65
lines changed

CMakeLists.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,7 @@ add_compile_options(-Wall -Werror -Wpedantic -Werror=vla -DconfigSUPPORT_STATIC_
1313
set(MKLITTLEFS_BIN ${CMAKE_CURRENT_SOURCE_DIR}/tools/mklittlefs)
1414
set(LFS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/littlefs_data)
1515
set(LFS_OUTPUT_BIN ${CMAKE_CURRENT_BINARY_DIR}/littlefs.bin)
16-
add_custom_command(
17-
OUTPUT ${LFS_OUTPUT_BIN}
16+
add_custom_target(build_littlefs ALL
1817
COMMAND ${MKLITTLEFS_BIN} -s 0x20000 -b 4096 -p 256 -c ${LFS_SOURCE_DIR} ${LFS_OUTPUT_BIN}
19-
COMMENT "Building LittleFS image"
2018
VERBATIM
21-
)
22-
add_custom_target(build_littlefs ALL
23-
DEPENDS ${LFS_OUTPUT_BIN}
2419
)

littlefs_data/config.txt

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,71 @@
1-
# Interlock Config
1+
####################
2+
# Interlock Config #
3+
####################
24

5+
# Lines starting with # or ; are ignored.
6+
# LF or CRLF line endings are allowed.
7+
8+
#
9+
# Config version
10+
#
311
CONFIG_VERSION=CONFIG_VERSION
4-
DEVICE_NAME=DEVICE_NAME
5-
DEVICE_TYPE=DEVICE_TYPE
6-
PORTAL_ADDRESS=PORTAL_ADDRESS
7-
API_KEY=API_KEY
8-
LED_COUNT=LED_COUNT
9-
LED_TYPE=LED_TYPE
10-
RFID_READER_TYPE=RFID_READER_TYPE
11-
WIFI_SSID=WIFI_SSID
12-
WIFI_PSK=WIFI_PSK
13-
SKELETON_CARD=SKELETON_CARD
12+
13+
#
14+
# Device config
15+
#
16+
17+
; The name used for registration with the portal
18+
DEVICE_NAME=TestInterlock
19+
20+
; The type of the device
21+
; Allowed: DOOR|INTERLOCK
22+
DEVICE_TYPE=DOOR
23+
24+
#
25+
# Portal config
26+
#
27+
28+
; Address used to connect to the portal. No trailing slash.
29+
; e.g. portal.hsbne.org
30+
PORTAL_ADDRESS=www.howmyssl/com/a/check
31+
32+
; Port used for websocket communications with the portal
33+
PORTAL_PORT=443
34+
35+
; Secret API key for the portal's access API
36+
PORTAL_API_KEY=123456789abcdefg
37+
38+
#
39+
# LED config
40+
#
41+
42+
; Number of LEDs on the device
43+
LED_COUNT=20
44+
45+
; Type of LED lights. Newer interlocks typically use BGRW
46+
; Allowed: RGBW|BGRW
47+
LED_TYPE=BGRW
48+
49+
#
50+
# RFID config
51+
#
52+
53+
; The type of RFID reader. Almost all interlocks use the RF125PS reader.
54+
; Some very old interlocks use the legacy reader.
55+
; Allowed: RF125PS|LEGACY
56+
RFID_READER_TYPE=RF125PS
57+
58+
; The number of an RFID card that can always unlock the interlock.
59+
; e.g. 714456
60+
; Set to NONE to disable this feature
61+
RFID_SKELETON_CARD=NONE
62+
63+
#
64+
# Wifi config
65+
#
66+
67+
; WiFi name
68+
WIFI_SSID=FBIVan
69+
70+
; WiFi password
71+
WIFI_PSK=password

main/config.c

Lines changed: 251 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "config.h"
2+
#include <stdbool.h>
23
#include <stddef.h>
4+
#include <stdint.h>
35
#include <stdio.h>
46
#include <string.h>
57
#include "core.h"
@@ -54,6 +56,11 @@ const char* config_err_to_str(config_err_t err) {
5456
return "CONFIG_ERR_FILE_SYSTEM";
5557
case CONFIG_ERR_TRUNCATED:
5658
return "CONFIG_ERR_TRUNCATED";
59+
case CONFIG_ERR_INVALID_VALUE:
60+
return "CONFIG_ERR_INVALID_VALUE";
61+
case CONFIG_ERR_N_ERRS:
62+
// Intentional fall through
63+
(void)0;
5764
}
5865
return "INVALID";
5966
}
@@ -63,15 +70,16 @@ const char* config_err_to_str(config_err_t err) {
6370
// =============================================================================
6471

6572
static const char* config_key_strings[CFG_KEY_N_KEYS] = {
66-
[CFG_KEY_API_KEY] = "API_KEY",
6773
[CFG_KEY_CONFIG_VERSION] = "CONFIG_VERSION",
6874
[CFG_KEY_DEVICE_NAME] = "DEVICE_NAME",
6975
[CFG_KEY_DEVICE_TYPE] = "DEVICE_TYPE",
7076
[CFG_KEY_LED_COUNT] = "LED_COUNT",
7177
[CFG_KEY_LED_TYPE] = "LED_TYPE",
7278
[CFG_KEY_PORTAL_ADDRESS] = "PORTAL_ADDRESS",
79+
[CFG_KEY_PORTAL_API_KEY] = "PORTAL_API_KEY",
80+
[CFG_KEY_PORTAL_PORT] = "PORTAL_PORT",
7381
[CFG_KEY_RFID_READER_TYPE] = "RFID_READER_TYPE",
74-
[CFG_KEY_SKELETON_CARD] = "SKELETON_CARD",
82+
[CFG_KEY_RFID_SKELETON_CARD] = "RFID_SKELETON_CARD",
7583
[CFG_KEY_WIFI_PSK] = "WIFI_PSK",
7684
[CFG_KEY_WIFI_SSID] = "WIFI_SSID",
7785
};
@@ -90,11 +98,12 @@ static const char* config_key_strings[CFG_KEY_N_KEYS] = {
9098
// valid if the function returns CONFIG_OK.
9199
//
92100
// On success, up to `size` bytes will be copied to `out_value`, which will
93-
// be null terminated for any `size` greater than zero.
101+
// be null terminated for any `size` greater than zero. Size is recommended to
102+
// be at least CONFIG_MAX_VALUE_LENGTH + 1.
94103
//
95104
// On failure, a relevant error code will be returned. The value in `out_value`
96105
// must be ignored.
97-
config_err_t config_value_get(config_key_t key, char* out_value, size_t size) {
106+
static config_err_t config_value_get(config_key_t key, char* out_value, size_t size) {
98107
// Validate the key
99108
if (0 > key || key >= CFG_KEY_N_KEYS) {
100109
return CONFIG_ERR_INVALID_ARG;
@@ -175,3 +184,241 @@ config_err_t config_value_get(config_key_t key, char* out_value, size_t size) {
175184

176185
return ret_val;
177186
}
187+
188+
// =============================================================================
189+
// Config
190+
// =============================================================================
191+
192+
typedef struct interlock_config {
193+
// Device
194+
device_type_t device_type;
195+
char device_name[CONFIG_MAX_VALUE_LENGTH + 1];
196+
197+
// Portal
198+
char portal_address[CONFIG_MAX_VALUE_LENGTH + 1];
199+
char portal_api_key[CONFIG_MAX_VALUE_LENGTH + 1];
200+
uint16_t portal_port;
201+
202+
// WIFI
203+
char wifi_ssid[CONFIG_MAX_VALUE_LENGTH + 1];
204+
char wifi_psk[CONFIG_MAX_VALUE_LENGTH + 1];
205+
206+
// LED
207+
uint16_t led_count;
208+
led_type_t led_type;
209+
210+
// RFID
211+
rfid_reader_type_t rfid_reader_type;
212+
bool rfid_use_skeleton_card;
213+
rfid_number_t skeleton_card;
214+
} interlock_config_t;
215+
216+
static bool config_str_to_device_type(const char* str, device_type_t* type) {
217+
if (0 == strcmp_icase(str, "DOOR")) {
218+
*type = DEVICE_TYPE_DOOR;
219+
return true;
220+
}
221+
222+
if (0 == strcmp_icase(str, "INTERLOCK")) {
223+
*type = DEVICE_TYPE_INTERLOCK;
224+
return true;
225+
}
226+
227+
return false;
228+
}
229+
230+
static bool config_str_to_led_type(const char* str, led_type_t* type) {
231+
if (0 == strcmp_icase(str, "RGBW")) {
232+
*type = LED_TYPE_RGBW;
233+
return true;
234+
}
235+
236+
if (0 == strcmp_icase(str, "BGRW")) {
237+
*type = LED_TYPE_BGRW;
238+
return true;
239+
}
240+
241+
return false;
242+
}
243+
244+
static bool config_str_to_rfid_reader_type(const char* str, rfid_reader_type_t* type) {
245+
if (0 == strcmp_icase(str, "RF125PS")) {
246+
*type = RFID_READER_TYPE_RF125PS;
247+
return true;
248+
}
249+
250+
if (0 == strcmp_icase(str, "LEGACY")) {
251+
*type = RFID_READER_TYPE_LEGACY;
252+
return true;
253+
}
254+
255+
return false;
256+
}
257+
258+
static bool config_str_to_u16(const char* str, uint16_t* val) {
259+
long l;
260+
if (!strtol_easy(str, &l)) {
261+
return false;
262+
}
263+
264+
if (l < 0 || l > UINT16_MAX) {
265+
return false;
266+
}
267+
268+
*val = (uint16_t)l;
269+
return true;
270+
}
271+
272+
static void config_read_From_file_log_error(config_key_t key, config_err_t err) {
273+
ESP_LOGE(TAG, "Error reading config value for %s: %s", config_key_strings[key], config_err_to_str(err));
274+
}
275+
276+
static void config_read_from_file_helper(config_key_t key, char* buffer, size_t buffer_size, uint32_t* status) {
277+
config_err_t err = config_value_get(key, buffer, buffer_size);
278+
if (CONFIG_OK != err) {
279+
config_read_From_file_log_error(key, err);
280+
*status |= (1 << err);
281+
}
282+
}
283+
284+
// Returns true if the config was successfully read.
285+
static bool config_read_from_file(interlock_config_t* config) {
286+
uint32_t status = 0; // Bit field of errors
287+
char buffer[CONFIG_MAX_VALUE_LENGTH + 1] = {0}; // Working buffer non string config items
288+
289+
memset(config, 0, sizeof(interlock_config_t));
290+
291+
// Device type
292+
config_read_from_file_helper(CFG_KEY_DEVICE_TYPE, buffer, sizeof(buffer), &status);
293+
if (!config_str_to_device_type(buffer, &config->device_type)) {
294+
status |= CONFIG_ERR_INVALID_ARG;
295+
}
296+
297+
// Device name
298+
config_read_from_file_helper(CFG_KEY_DEVICE_NAME, config->device_name, sizeof(config->device_name), &status);
299+
300+
// Portal address
301+
config_read_from_file_helper(CFG_KEY_PORTAL_ADDRESS, config->portal_address, sizeof(config->portal_address),
302+
&status);
303+
304+
// Portal API key
305+
config_read_from_file_helper(CFG_KEY_PORTAL_API_KEY, config->portal_api_key, sizeof(config->portal_api_key),
306+
&status);
307+
308+
// Portal port
309+
config_read_from_file_helper(CFG_KEY_PORTAL_PORT, buffer, sizeof(buffer), &status);
310+
if (!config_str_to_u16(buffer, &config->portal_port)) {
311+
status |= CONFIG_ERR_INVALID_ARG;
312+
}
313+
314+
// Wifi SSID
315+
config_read_from_file_helper(CFG_KEY_WIFI_SSID, config->wifi_ssid, sizeof(config->wifi_ssid), &status);
316+
317+
// Wifi PSK
318+
config_read_from_file_helper(CFG_KEY_WIFI_PSK, config->wifi_psk, sizeof(config->wifi_psk), &status);
319+
320+
// LED count
321+
config_read_from_file_helper(CFG_KEY_LED_COUNT, buffer, sizeof(buffer), &status);
322+
if (!config_str_to_u16(buffer, &config->led_count)) {
323+
config_read_From_file_log_error(CFG_KEY_LED_COUNT, CONFIG_ERR_INVALID_ARG);
324+
status |= CONFIG_ERR_INVALID_ARG;
325+
}
326+
327+
// LED Type
328+
config_read_from_file_helper(CFG_KEY_LED_TYPE, buffer, sizeof(buffer), &status);
329+
if (!config_str_to_led_type(buffer, &config->led_type)) {
330+
config_read_From_file_log_error(CFG_KEY_LED_TYPE, CONFIG_ERR_INVALID_ARG);
331+
status |= CONFIG_ERR_INVALID_ARG;
332+
}
333+
334+
// RFID reader type
335+
config_read_from_file_helper(CFG_KEY_RFID_READER_TYPE, buffer, sizeof(buffer), &status);
336+
if (!config_str_to_rfid_reader_type(buffer, &config->rfid_reader_type)) {
337+
config_read_From_file_log_error(CFG_KEY_RFID_READER_TYPE, CONFIG_ERR_INVALID_ARG);
338+
status |= CONFIG_ERR_INVALID_ARG;
339+
}
340+
341+
// RFID skeleton card
342+
long skeleton_card;
343+
config_read_from_file_helper(CFG_KEY_RFID_SKELETON_CARD, buffer, sizeof(buffer), &status);
344+
if (0 == strcmp_icase(buffer, "NONE")) {
345+
config->rfid_use_skeleton_card = false;
346+
config->skeleton_card = UINT64_MAX;
347+
} else if (strtol_easy(buffer, &skeleton_card) && skeleton_card > 0) {
348+
config->rfid_use_skeleton_card = true;
349+
config->skeleton_card = skeleton_card;
350+
} else {
351+
config_read_From_file_log_error(CFG_KEY_RFID_SKELETON_CARD, CONFIG_ERR_INVALID_ARG);
352+
status |= CONFIG_ERR_INVALID_ARG;
353+
}
354+
355+
// Print out any config errors:
356+
if (0 != status) {
357+
ESP_LOGE(TAG, "The following errors were encountered when reading the config file:");
358+
for (int i = 0; i < CONFIG_ERR_N_ERRS; i++) {
359+
if ((status & (1 << i)) && i != CONFIG_OK) {
360+
ESP_LOGE(TAG, " - %s", config_err_to_str(i));
361+
}
362+
}
363+
}
364+
365+
return 0 == status;
366+
}
367+
368+
static interlock_config_t config = {0};
369+
370+
bool config_init() {
371+
return config_read_from_file(&config);
372+
}
373+
374+
// =============================================================================
375+
// Getters
376+
// =============================================================================
377+
378+
device_type_t config_get_device_type(void) {
379+
return config.device_type;
380+
}
381+
382+
const char* config_get_device_name(void) {
383+
return config.device_name;
384+
}
385+
386+
const char* config_get_portal_address(void) {
387+
return config.portal_address;
388+
}
389+
390+
const char* config_get_portal_api_key(void) {
391+
return config.portal_api_key;
392+
}
393+
394+
uint16_t config_get_portal_port(void) {
395+
return config.portal_port;
396+
}
397+
398+
const char* config_get_wifi_ssid(void) {
399+
return config.wifi_ssid;
400+
}
401+
402+
const char* config_get_wifi_psk(void) {
403+
return config.wifi_psk;
404+
}
405+
406+
uint16_t config_get_led_count(void) {
407+
return config.led_count;
408+
}
409+
410+
led_type_t config_get_led_type(void) {
411+
return config.led_type;
412+
}
413+
414+
rfid_reader_type_t config_get_rfid_reader_type(void) {
415+
return config.rfid_reader_type;
416+
}
417+
418+
bool config_get_rfid_use_skeleton_card(void) {
419+
return config.rfid_use_skeleton_card;
420+
}
421+
422+
rfid_number_t config_get_skeleton_card(void) {
423+
return config.skeleton_card;
424+
}

0 commit comments

Comments
 (0)