19
19
#include "mgos.h"
20
20
#include "mgos_homeassistant_automation.h"
21
21
#include "mgos_homeassistant_barometer.h"
22
+ #include "mgos_homeassistant_bh1750.h"
22
23
#include "mgos_homeassistant_gpio.h"
23
24
#include "mgos_homeassistant_si7021.h"
24
- #include "mgos_homeassistant_bh1750.h"
25
25
#include "mgos_mqtt.h"
26
26
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
+
27
35
static struct mgos_homeassistant * s_homeassistant = NULL ;
28
36
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
+
29
47
static void mgos_homeassistant_mqtt_connect (struct mg_connection * nc , const char * client_id , struct mg_send_mqtt_handshake_opts * opts , void * fn_arg ) {
30
48
LOG (LL_DEBUG , ("Setting will topic='%s' payload='offline', for when we disconnect" , mgos_sys_config_get_device_id ()));
31
49
opts -> will_topic = mgos_sys_config_get_device_id ();
@@ -89,72 +107,44 @@ bool mgos_homeassistant_fromfile(struct mgos_homeassistant *ha, const char *file
89
107
return ret ;
90
108
}
91
109
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 ;
93
113
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 ;
94
122
void * h = NULL ;
95
123
int idx ;
96
124
97
125
char * name = NULL ;
98
126
99
127
if (!ha || !json ) return false;
128
+ size_t json_sz = strlen (json );
100
129
101
130
// Set global config elements
102
- json_scanf (json , strlen ( json ) , "{name:%Q}" , & name );
131
+ json_scanf (json , json_sz , "{name:%Q}" , & name );
103
132
if (name ) {
104
133
if (ha -> node_name ) free (ha -> node_name );
105
134
ha -> node_name = strdup (name );
106
135
}
107
136
108
137
// 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" ));
154
144
}
155
145
156
146
// 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 ) {
158
148
struct mgos_homeassistant_automation * a ;
159
149
160
150
if (!(a = mgos_homeassistant_automation_create (val ))) {
@@ -173,7 +163,44 @@ struct mgos_homeassistant *mgos_homeassistant_get_global() {
173
163
return s_homeassistant ;
174
164
}
175
165
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
+
176
179
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
+
177
204
s_homeassistant = calloc (1 , sizeof (struct mgos_homeassistant ));
178
205
if (!s_homeassistant ) return false;
179
206
0 commit comments