Skip to content

Commit 4e368fe

Browse files
committed
Config .provider clause handler infrastructure
Add ha_provider_cfg_handler: cfg entry handler callback type. Add mgos_homeassistant_register_provider(): API for adding providers. mgos_homeassistant_fromjson(): - Factor looping through .provider.foo config arrays out into mgos_homeassistant_fromjson_arr(). - Factor handling built-in providers (barometer, bh1750, gpio, si7021) out into registering them in mgos_homeassistant_init(). (*) Also order #include directives as clang-format wants.
1 parent 7652d38 commit 4e368fe

File tree

2 files changed

+79
-49
lines changed

2 files changed

+79
-49
lines changed

include/mgos_homeassistant.h

+3
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
extern "C" {
2323
#endif
2424

25+
typedef bool (*ha_provider_cfg_handler)(struct mgos_homeassistant *ha, struct json_token val);
26+
2527
struct mgos_homeassistant *mgos_homeassistant_get_global(void);
2628
bool mgos_homeassistant_fromfile(struct mgos_homeassistant *ha, const char *filename);
2729
bool mgos_homeassistant_fromjson(struct mgos_homeassistant *ha, const char *json);
2830
bool mgos_homeassistant_clear(struct mgos_homeassistant *ha);
31+
bool mgos_homeassistant_register_provider(const char *provider, ha_provider_cfg_handler cfg_handler, const char *mos_mod);
2932

3033
#ifdef __cplusplus
3134
}

src/mgos_homeassistant.c

+76-49
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,31 @@
1919
#include "mgos.h"
2020
#include "mgos_homeassistant_automation.h"
2121
#include "mgos_homeassistant_barometer.h"
22+
#include "mgos_homeassistant_bh1750.h"
2223
#include "mgos_homeassistant_gpio.h"
2324
#include "mgos_homeassistant_si7021.h"
24-
#include "mgos_homeassistant_bh1750.h"
2525
#include "mgos_mqtt.h"
2626

27+
struct provider {
28+
ha_provider_cfg_handler cfg_handler;
29+
const char *module;
30+
const char *provider;
31+
SLIST_ENTRY(provider) entry;
32+
};
33+
static SLIST_HEAD(, provider) providers;
34+
2735
static struct mgos_homeassistant *s_homeassistant = NULL;
2836

37+
static struct provider *mgos_homeassistant_get_provider(const char *provider, size_t len) {
38+
struct provider *p;
39+
if (!len) {
40+
SLIST_FOREACH(p, &providers, entry) if (!strcmp(p->provider, provider)) return p;
41+
} else {
42+
SLIST_FOREACH(p, &providers, entry) if (!strncmp(p->provider, provider, len) && !p->provider[len]) return p;
43+
}
44+
return NULL;
45+
}
46+
2947
static void mgos_homeassistant_mqtt_connect(struct mg_connection *nc, const char *client_id, struct mg_send_mqtt_handshake_opts *opts, void *fn_arg) {
3048
LOG(LL_DEBUG, ("Setting will topic='%s' payload='offline', for when we disconnect", mgos_sys_config_get_device_id()));
3149
opts->will_topic = mgos_sys_config_get_device_id();
@@ -89,72 +107,44 @@ bool mgos_homeassistant_fromfile(struct mgos_homeassistant *ha, const char *file
89107
return ret;
90108
}
91109

92-
bool mgos_homeassistant_fromjson(struct mgos_homeassistant *ha, const char *json) {
110+
static void mgos_homeassistant_fromjson_arr(struct mgos_homeassistant *ha, struct provider *p, struct json_token *arr) {
111+
struct json_token *h = NULL;
112+
int idx;
93113
struct json_token val;
114+
while ((h = json_next_elem(arr->ptr, arr->len, h, "", &idx, &val)) != NULL) {
115+
if (p->cfg_handler(ha, val)) continue;
116+
LOG(LL_WARN, ("Failed to add object (provider %s, index %d), JSON: %.*s", p->provider, idx, val.len, val.ptr));
117+
}
118+
}
119+
120+
bool mgos_homeassistant_fromjson(struct mgos_homeassistant *ha, const char *json) {
121+
struct json_token key, val;
94122
void *h = NULL;
95123
int idx;
96124

97125
char *name = NULL;
98126

99127
if (!ha || !json) return false;
128+
size_t json_sz = strlen(json);
100129

101130
// Set global config elements
102-
json_scanf(json, strlen(json), "{name:%Q}", &name);
131+
json_scanf(json, json_sz, "{name:%Q}", &name);
103132
if (name) {
104133
if (ha->node_name) free(ha->node_name);
105134
ha->node_name = strdup(name);
106135
}
107136

108137
// Read providers
109-
while ((h = json_next_elem(json, strlen(json), h, ".provider.gpio", &idx, &val)) != NULL) {
110-
if (!mgos_homeassistant_gpio_fromjson(ha, val)) {
111-
LOG(LL_WARN, ("Failed to add object from provider gpio, index %d, json "
112-
"follows:%.*s",
113-
idx, (int) val.len, val.ptr));
114-
}
115-
}
116-
117-
while ((h = json_next_elem(json, strlen(json), h, ".provider.si7021", &idx, &val)) != NULL) {
118-
#ifdef MGOS_HAVE_SI7021_I2C
119-
if (!mgos_homeassistant_si7021_fromjson(ha, val)) {
120-
LOG(LL_WARN, ("Failed to add object from provider si7021, index %d, json "
121-
"follows:%.*s",
122-
idx, (int) val.len, val.ptr));
123-
}
124-
#else
125-
LOG(LL_ERROR, ("provider.si7021 config found: Add si7021-i2c to mos.yml, "
126-
"skipping .. "));
127-
#endif
128-
}
129-
130-
while ((h = json_next_elem(json, strlen(json), h, ".provider.bh1750", &idx, &val)) != NULL) {
131-
#ifdef MGOS_HAVE_BH1750
132-
if (!mgos_homeassistant_bh1750_fromjson(ha, val)) {
133-
LOG(LL_WARN, ("Failed to add object from provider bh1750, index %d, json "
134-
"follows:%.*s",
135-
idx, (int) val.len, val.ptr));
136-
}
137-
#else
138-
LOG(LL_ERROR, ("provider.bh1750 config found: Add bh1750-i2c to mos.yml, "
139-
"skipping .. "));
140-
#endif
141-
}
142-
143-
while ((h = json_next_elem(json, strlen(json), h, ".provider.barometer", &idx, &val)) != NULL) {
144-
#ifdef MGOS_HAVE_BAROMETER
145-
if (!mgos_homeassistant_barometer_fromjson(ha, val)) {
146-
LOG(LL_WARN, ("Failed to add object from provider barometer, index %d, json "
147-
"follows:%.*s",
148-
idx, (int) val.len, val.ptr));
149-
}
150-
#else
151-
LOG(LL_ERROR, ("provider.barometer config found: Add barometer to mos.yml, "
152-
"skipping .. "));
153-
#endif
138+
while ((h = json_next_key(json, json_sz, h, ".provider", &key, &val)) != NULL) {
139+
struct provider *p = mgos_homeassistant_get_provider(key.ptr, key.len);
140+
if (p && p->cfg_handler)
141+
mgos_homeassistant_fromjson_arr(ha, p, &val);
142+
else
143+
LOG(LL_ERROR, ("provider.%.*s config found: add %s to mos.yml, skipping...", key.len, key.ptr, p ? p->module : "the module implementing it"));
154144
}
155145

156146
// Read automations
157-
while ((h = json_next_elem(json, strlen(json), h, ".automation", &idx, &val)) != NULL) {
147+
while ((h = json_next_elem(json, json_sz, h, ".automation", &idx, &val)) != NULL) {
158148
struct mgos_homeassistant_automation *a;
159149

160150
if (!(a = mgos_homeassistant_automation_create(val))) {
@@ -173,7 +163,44 @@ struct mgos_homeassistant *mgos_homeassistant_get_global() {
173163
return s_homeassistant;
174164
}
175165

166+
bool mgos_homeassistant_register_provider(const char *provider, ha_provider_cfg_handler cfg_handler, const char *module) {
167+
struct provider *p;
168+
if (!provider || !(!cfg_handler ^ !module)) return false;
169+
if (mgos_homeassistant_get_provider(provider, 0)) return false;
170+
if (!(p = malloc(sizeof(*p)))) return false;
171+
172+
p->cfg_handler = cfg_handler;
173+
p->module = module;
174+
p->provider = provider;
175+
SLIST_INSERT_HEAD(&providers, p, entry);
176+
return true;
177+
}
178+
176179
bool mgos_homeassistant_init(void) {
180+
SLIST_INIT(&providers);
181+
mgos_homeassistant_register_provider("barometer",
182+
#ifdef MGOS_HAVE_BAROMETER
183+
mgos_homeassistant_barometer_fromjson, NULL
184+
#else
185+
NULL, "barometer"
186+
#endif
187+
);
188+
mgos_homeassistant_register_provider("bh1750",
189+
#ifdef MGOS_HAVE_BH1750
190+
mgos_homeassistant_bh1750_fromjson, NULL
191+
#else
192+
NULL, "bh1750-i2c"
193+
#endif
194+
);
195+
mgos_homeassistant_register_provider("gpio", mgos_homeassistant_gpio_fromjson, NULL);
196+
mgos_homeassistant_register_provider("si7021",
197+
#ifdef MGOS_HAVE_SI7021_I2C
198+
mgos_homeassistant_si7021_fromjson, NULL
199+
#else
200+
NULL, "si7021-i2c"
201+
#endif
202+
);
203+
177204
s_homeassistant = calloc(1, sizeof(struct mgos_homeassistant));
178205
if (!s_homeassistant) return false;
179206

0 commit comments

Comments
 (0)