11static const char*
TAG =
"PLG_MAN";
13static std::string
str_or(
const cJSON* node,
const char* key,
const char* dflt =
"")
15 const cJSON* item = cJSON_GetObjectItemCaseSensitive(node, key);
16 if (cJSON_IsString(item) && item->valuestring) {
17 return item->valuestring;
22static bool parse_api_level(
const std::string& s, uint16_t& major, uint16_t& minor)
24 if (s.empty())
return false;
25 const char* dot = std::strchr(s.c_str(),
'.');
26 if (!dot)
return false;
27 major =
static_cast<uint16_t
>(std::atoi(s.c_str()));
28 minor =
static_cast<uint16_t
>(std::atoi(dot + 1));
32static void parse_localized(
const cJSON* root, std::map<std::string, LocalizedString>& out)
34 if (!cJSON_IsObject(root))
return;
35 for (cJSON* it = root->child; it !=
nullptr; it = it->next) {
36 if (!it->string || !cJSON_IsObject(it))
continue;
38 for (cJSON* lang_it = it->child; lang_it !=
nullptr; lang_it = lang_it->next) {
39 if (lang_it->string && cJSON_IsString(lang_it) && lang_it->valuestring) {
40 ls.
by_lang[lang_it->string] = lang_it->valuestring;
43 out[it->string] = std::move(ls);
49 if (!cJSON_IsObject(root))
return;
51 auto get_bool = [&](
const char* key,
bool dflt) {
52 const cJSON* n = cJSON_GetObjectItemCaseSensitive(root, key);
53 return cJSON_IsBool(n) ? cJSON_IsTrue(n) : dflt;
56 cap.
wifi = get_bool(
"wifi",
false);
57 cap.
ble = get_bool(
"ble",
false);
58 cap.
http = get_bool(
"http",
false);
59 cap.
socket = get_bool(
"socket",
false);
62 cap.
sao = get_bool(
"sao",
false);
63 cap.
grove = get_bool(
"grove",
false);
65 cap.
background = get_bool(
"background",
false);
66 cap.
usb_cdc = get_bool(
"usb_cdc",
false);
68 cap.
autoload = get_bool(
"autoload",
false);
69 cap.
vfat = get_bool(
"vfat",
false);
73 auto get_int_array_u8 = [&](
const char* key, std::vector<uint8_t>& out) {
74 const cJSON* n = cJSON_GetObjectItemCaseSensitive(root, key);
75 if (!cJSON_IsArray(n))
return;
76 for (cJSON* it = n->child; it !=
nullptr; it = it->next) {
77 if (cJSON_IsNumber(it)) {
78 out.push_back(
static_cast<uint8_t
>(it->valueint));
83 auto get_str_array = [&](
const char* key, std::vector<std::string>& out) {
84 const cJSON* n = cJSON_GetObjectItemCaseSensitive(root, key);
85 if (!cJSON_IsArray(n))
return;
86 for (cJSON* it = n->child; it !=
nullptr; it = it->next) {
87 if (cJSON_IsString(it) && it->valuestring) {
88 out.push_back(it->valuestring);
93 get_str_array (
"rmem", cap.
rmem);
94 get_str_array (
"ecc", cap.
ecc);
97 get_int_array_u8 (
"gpio_pins", cap.
gpio_pins);
98 get_int_array_u8 (
"pwm_pins", cap.
pwm_pins);
99 get_int_array_u8 (
"adc_pins", cap.
adc_pins);
100 get_int_array_u8 (
"i2c_bus", cap.
i2c_bus);
103static void parse_prereqs(
const cJSON* root, std::vector<PrerequisiteSpec>& out)
105 if (!cJSON_IsObject(root))
return;
106 for (cJSON* it = root->child; it !=
nullptr; it = it->next) {
107 if (!it->string || !cJSON_IsObject(it))
continue;
109 spec.
name = it->string;
111 for (cJSON* p = it->child; p !=
nullptr; p = p->next) {
112 if (!p->string)
continue;
113 if (cJSON_IsString(p) && p->valuestring) {
114 if (std::strcmp(p->string,
"on_fail") == 0) {
117 spec.
params[p->string] = p->valuestring;
119 }
else if (cJSON_IsNumber(p)) {
120 spec.
params[p->string] = std::to_string(p->valueint);
121 }
else if (cJSON_IsBool(p)) {
122 spec.
params[p->string] = cJSON_IsTrue(p) ?
"true" :
"false";
125 out.push_back(std::move(spec));
131 cJSON* root = cJSON_ParseWithLength(json, len);
144 LOG_E(
TAG,
"manifest missing required fields");
155 if (
const cJSON* lm = cJSON_GetObjectItemCaseSensitive(root,
"linear_memory_kb");
156 cJSON_IsNumber(lm)) {
160 if (
const cJSON* i18n = cJSON_GetObjectItemCaseSensitive(root,
"i18n")) {
In-memory representation of a plugin's meta.json.
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_E(tag, fmt,...)
static void parse_prereqs(const cJSON *root, std::vector< PrerequisiteSpec > &out)
static void parse_capabilities(const cJSON *root, PluginCapabilities &cap)
static std::string str_or(const cJSON *node, const char *key, const char *dflt="")
static void parse_localized(const cJSON *root, std::map< std::string, LocalizedString > &out)
static bool parse_api_level(const std::string &s, uint16_t &major, uint16_t &minor)
std::map< std::string, std::string > by_lang
std::vector< std::string > rmem
std::vector< std::string > ecc
bool vfat
Allow sandboxed file access on the plugins FAT partition via the host_fs_* API. The plugin can only t...
std::vector< uint8_t > i2c_bus
std::vector< uint8_t > adc_pins
std::vector< uint8_t > gpio_pins
bool autoload
Start this plugin as a resident background instance at badge boot. Plugins without this flag stay unl...
std::string nvs_namespace
std::vector< std::string > ble_service_uuids
std::vector< std::string > message_types
std::vector< uint8_t > pwm_pins
bool background
Keep running and ticking in the background after the user leaves the plugin's view,...
std::vector< PrerequisiteSpec > prerequisites
uint32_t linear_memory_kb
std::map< std::string, LocalizedString > i18n_meta
static bool parse(const char *json, size_t len, PluginManifest &out)
Parse meta.json content. Returns false on schema errors.
std::string host_api_level_min
std::string default_language
PluginCapabilities capabilities
std::map< std::string, LocalizedString > i18n_strings
std::map< std::string, std::string > params