Closed Harvie closed 4 years ago
Changes made, you can now examine mgos_libs_info
to get information about libraries.
This requires changes to mos
CLI, i am pushing mos-latest
now.
Thanks a lot. I will take a look.
We have managed to list all modules like this:
#include "mgos_app.h"
...
#ifdef MGOS_LIB_INFO_VERSION
/* iterate over all mongoose modules compiled in firmware */
for (const struct mgos_lib_info *l = mgos_libs_info; l->name != NULL; l++)
{
LOG(LL_INFO,("FHS DETECTED MODULE: %s version %s", l->name, l->version));
}
#endif
I haven't checked yet that mgos_libs_info
is actually NULL
terminated. Also i am yet to modify the code to use json_printf_array()
(from frozen) to convert the array to JSON...
For some reason i wasn't able to iterate like this:
for(int i = 0; i < sizeof(mgos_libs_info) / sizeof(struct mgos_lib_info); i++) {...}
didn't compiled...
You can see by yourself the generated file by browsing the file contained inside build/gen/mgos_deps_init.c
Here's a snippet of the last part of mgos_libs_info
:
// "rpc-mqtt". deps: [ "aws" "core" "mqtt" "rpc-common" ]
{.name = "rpc-mqtt", .version = "1.0", .init = mgos_rpc_mqtt_init},
// "rpc-service-config". deps: [ "core" "rpc-common" ]
{.name = "rpc-service-config", .version = "1.0", .init = mgos_rpc_service_config_init},
// "rpc-service-fs". deps: [ "core" "rpc-common" ]
{.name = "rpc-service-fs", .version = "1.0", .init = mgos_rpc_service_fs_init},
// "rpc-service-gpio". deps: [ "core" "rpc-common" ]
{.name = "rpc-service-gpio", .version = "1.0", .init = mgos_rpc_service_gpio_init},
// "rpc-service-i2c". deps: [ "core" "i2c" "rpc-common" ]
{.name = "rpc-service-i2c", .version = "1.0", .init = mgos_rpc_service_i2c_init},
// "rpc-service-ota". deps: [ "core" "ota-http-client" "rpc-common" ]
{.name = "rpc-service-ota", .version = "1.0", .init = mgos_rpc_service_ota_init},
// "rpc-service-wifi". deps: [ "core" "rpc-common" "wifi" ]
{.name = "rpc-service-wifi", .version = "1.0", .init = mgos_rpc_service_wifi_init},
// "rpc-uart". deps: [ "core" "rpc-common" ]
{.name = "rpc-uart", .version = "1.0", .init = mgos_rpc_uart_init},
// Last entry.
{.name = NULL},
};
As you can see, the last entry will have its name
member as NULL, you can use that information to iterate over the array and stop once NULL is found.
When i try to do sizeof(mgos_libs_info) / sizeof(struct mgos_lib_info)
, the compilation fails with following message:
Invalid application of 'sizeof' to incomplete type 'constr struct mgos_lib_info[]';
Maybe it's caused by the struct being defined in ifndef block... Can you please check if this might cause some files being compiled only with struct name without full declaration?
#ifndef MGOS_LIB_INFO_VERSION
struct mgos_lib_info {
const char *name;
const char *version;
bool (*init)(void);
};
#endif
Are you using this header? https://github.com/cesanta/mongoose-os/blob/master/include/mgos_app.h
The size of mgos_libs_info
can't be determined at compile time. It is declared extern const struct mgos_lib_info mgos_libs_info[];.
Without the extern
keyword the compile error would be array size missing
.
The best way to iterate it is
for (const struct mgos_lib_info *info = mgos_libs_info; info->name != NULL;
info++) {
LOG(LL_INFO, ("name: %s, version: %s", info->name, info->version));
}
@DrBomb yes. i am including mgos_app.h
@nliviu i am doing this, but i want to compile the list to JSON, so i can send it over network in reasonable format... I probably only need sizeof(mgos_libs_info)
to preallocate enough space in buffer to fit whole JSON. I've figured that's about right. I probably should call strlen()
on all elements in the first pass, allocate and compile json in second pass, but this seemed easier to do...
Originaly i was thinking that it can be done by frozen json library, but i was not able to figure that out ( see https://github.com/cesanta/frozen/issues/58 ). So i came up with this ugly hack, but it has the previously mentioned problem...
#ifdef MGOS_LIB_INFO_VERSION
char mgos_libs_info_json[sizeof(mgos_libs_info)];
/* iterate over all mongoose modules compiled in firmware and produce JSON object with the list */
mgos_libs_info_json[0]=0;
strcat(mgos_libs_info_json, "{\"mgos_libs\":{");
for (const struct mgos_lib_info *l = mgos_libs_info; l->name != NULL; l++)
{
LOG(LL_INFO,("FHS DETECTED MODULE: %s version %s", l->name, l->version));
strcat(mgos_libs_info_json, "\"");
strcat(mgos_libs_info_json, l->name);
strcat(mgos_libs_info_json, "\":\"");
strcat(mgos_libs_info_json, l->version);
strcat(mgos_libs_info_json, "\"");
if((l+1)->name != NULL) strcat(mgos_libs_info_json, ",");
}
strcat(mgos_libs_info_json, "}}");
LOG(LL_INFO,("FHS DETECTED MODULES SIZE %d JSON: %s", sizeof(mgos_libs_info), mgos_libs_info_json);
#endif
Maybe i can try to include mgos_deps_init.c
directly... That worked for me when i've been doing experiments outside of mongoose ecosystem (just plain gcc on linux).
Maybe i can try to include mgos_deps_init.c directly
oh god, no! please don't do that :)
I probably only need sizeof(mgos_libs_info) to preallocate enough space in buffer to fit whole JSON
no, you need to grow your output buffer as needed.
void list_libs(void) {
struct mbuf mb;
struct json_out out = JSON_OUT_MBUF(&mb);
mbuf_init(&mb, 200);
json_printf(&out, "[\n");
for (const struct mgos_lib_info *li = mgos_libs_info; li->name != NULL; li++) {
if (mb.len > 2) {
json_printf(&out, ",\n");
}
json_printf(&out, " {name: %Q, version: %Q}", li->name, li->version);
}
json_printf(&out, "\n]\n");
printf("%.*s", (int) mb.len, mb.buf);
mbuf_free(&mb);
}
Hello, i would like to get list of names of active mongoose modules during runtime. Can you please make data from descrs[] array accesible using some header file which can be included in my modules?
I want to use this to send JSON list of modules to my cloud/server, so i know what modules/capabilities each device provides and therefore i know which features i can use... Because i have several devices which share some of the modules, while other modules are specific. It makes more sense to me than using several "versions" of API for each device configuration. This way i would simply know what modules are present in the device, so i can write nice modular API on the server.
BTW if you add version of each module to the list, it might be usefull as well.
Thanks