Added support for ubus array in dynamic addition parameters using JSON file + example of JSON file

This commit is contained in:
Amin Ben Ramdhane 2020-04-09 16:48:34 +01:00
parent 53ceedd990
commit 63d449df13
8 changed files with 394 additions and 48 deletions

View file

@ -238,6 +238,8 @@ The bbfdm library allows all applications installed on the box to import its own
The application should bring its JSON file under **'/etc/bbfdm/json/'** path with **UCI** and **UBUS** mappings. The new added parameters will be automatically shown by icwmp and uspd/obuspa.
To build a new JSON file, you can use **example.json file** under **dynamic_parameters/json** folder to help you build it.
**1. Object without instance:**
```plain
"Device.CWMP.": {
@ -273,9 +275,32 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit
}
```
- **UBUS command:** ubus call dsl status | jsonfilter -e @.line
```plain
"Device.DSL.Line.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl",
"method": "status",
"args": {},
"key": "line"
}
}
}
```
**3. Parameter under object with instance:**
- **UCI command:** uci get wireless.@wifi-device[0].country<br/>
- **UCI command:** uci get wireless.@wifi-device[0].country
- **@i:** is the number of instance object
```plain
"Country": {
"type": "string",
@ -420,7 +445,7 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit
The application should bring its plugin(library) file under **'/usr/lib/bbfdm/'** path that contains the sub tree of **Objects/Parameters** and the related functions **Get/Set/Add/Delete/Operate**. The new added objects, parameters and operates will be automatically shown by icwmp and uspd/obuspa.
To build a new library, you can use **example source code** under **library** folder to help you build it.
To build a new library, you can use **example source code** under **dynamic_parameters/library** folder to help you build it.
Each library should contains two Root table named **“tRootDynamicObj”** and **“tRootDynamicOperate”** to define the parant path for each new object and operate.

View file

@ -256,39 +256,39 @@ static int check_json_root_obj(struct dmctx *ctx, char *in_param_json, DMOBJ **r
int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
//UCI: arg1=type :: arg2=uci_file :: arg3=uci_section_type :: arg4=uci_dmmap_file :: arg5="" :: arg6=""
char *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL, *prefix_obj = NULL, *object = NULL;
char buf_instance[64] = "", buf_alias[64] = "";
struct dm_json_parameter *pleaf;
char *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL, *arg5 = NULL, *arg6 = NULL;
char *obj = generate_obj_without_instance(parent_node->current_object, true);
generate_prefixobj_and_obj_full_obj(parent_node->current_object, &prefix_obj, &object);
snprintf(buf_instance, sizeof(buf_instance), "%s_instance", object);
snprintf(buf_alias, sizeof(buf_alias), "%s_alias", object);
for (int i = 0; buf_instance[i]; i++) {
buf_instance[i] = tolower(buf_instance[i]);
}
for (int i = 0; buf_alias[i]; i++) {
buf_alias[i] = tolower(buf_alias[i]);
}
list_for_each_entry(pleaf, &json_list, list) {
if (strcmp(pleaf->name, obj) == 0) {
arg1 = pleaf->arg1;
arg2 = pleaf->arg2;
arg3 = pleaf->arg3;
arg4 = pleaf->arg4;
arg5 = pleaf->arg5;
arg6 = pleaf->arg6;
break;
}
}
if (arg1 && strcmp(arg1, "uci") == 0) {
//UCI: arg1=type :: arg2=uci_file :: arg3=uci_section_type :: arg4=uci_dmmap_file :: arg5="" :: arg6=""
char buf_instance[64] = "", buf_alias[64] = "", *prefix_obj = NULL, *object = NULL;
char *instance = NULL, *instnbr = NULL;
struct dmmap_dup *p;
LIST_HEAD(dup_list);
generate_prefixobj_and_obj_full_obj(parent_node->current_object, &prefix_obj, &object);
snprintf(buf_instance, sizeof(buf_instance), "%s_instance", object);
snprintf(buf_alias, sizeof(buf_alias), "%s_alias", object);
for (int i = 0; buf_instance[i]; i++)
buf_instance[i] = tolower(buf_instance[i]);
for (int i = 0; buf_alias[i]; i++)
buf_alias[i] = tolower(buf_alias[i]);
if(arg2 && arg3 && arg4) {
synchronize_specific_config_sections_with_dmmap(arg2, arg3, arg4, &dup_list);
list_for_each_entry(p, &dup_list, list) {
@ -299,6 +299,25 @@ int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *
}
free_dmmap_config_dup_list(&dup_list);
}
else if (arg1 && strcmp(arg1, "ubus") == 0) {
//UBUS: arg1=type :: arg2=ubus_object :: arg3=ubus_method :: arg4=ubus_args1 :: arg5=ubus_args2 :: arg6=ubus_key
json_object *res = NULL, *dyn_obj = NULL, *arrobj = NULL;
char *idx, *idx_last = NULL;
int id = 0, j = 0;
if (arg2 && arg3 && arg4 && arg5)
dmubus_call(arg2, arg3, UBUS_ARGS{{arg4, arg5, String}}, 1, &res);
else
dmubus_call(arg2, arg3, UBUS_ARGS{{}}, 0, &res);
if (res && arg6) {
dmjson_foreach_obj_in_array(res, arrobj, dyn_obj, j, 1, arg6) {
idx = handle_update_instance(1, dmctx, &idx_last, update_instance_without_section, 1, ++id);
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)dyn_obj, idx) == DM_STOP)
break;
}
}
}
return 0;
}
@ -431,20 +450,30 @@ static int getvalue_param(char *refparam, struct dmctx *ctx, void *data, char *i
//UBUS: arg1=type :: arg2=ubus_object :: arg3=ubus_method :: arg4=ubus_args1 :: arg5=ubus_args2 :: arg6=ubus_key
json_object *res = NULL;
if (arg2 && arg3 && arg4 && arg5) {
if (data && (strcmp(arg5, "@Name") == 0))
dmubus_call(arg2, arg3, UBUS_ARGS{{arg4, section_name((struct uci_section *)data), String}}, 1, &res);
else
dmubus_call(arg2, arg3, UBUS_ARGS{{arg4, arg5, String}}, 1, &res);
char arg2_1[128] = {0}, *opt = NULL;
if ((opt = strstr(arg2, "@Name"))) {
*opt = '\0';
snprintf(arg2_1, sizeof(arg2_1), "%s%s", arg2, section_name((struct uci_section *)data));
} else if ((opt = strstr(arg2, "@i-1"))) {
*opt = '\0';
snprintf(arg2_1, sizeof(arg2_1), "%s%d", arg2, atoi(instance) - 1);
} else {
strncpy(arg2_1, arg2, sizeof(arg2_1) - 1);
}
} else if (arg2 && arg3) {
dmubus_call(arg2, arg3, UBUS_ARGS{{}}, 0, &res);
if (arg4 && arg5) {
if (data && (strcmp(arg5, "@Name") == 0))
dmubus_call(arg2_1, arg3, UBUS_ARGS{{arg4, section_name((struct uci_section *)data), String}}, 1, &res);
else
dmubus_call(arg2_1, arg3, UBUS_ARGS{{arg4, arg5, String}}, 1, &res);
} else {
dmubus_call(arg2_1, arg3, UBUS_ARGS{{}}, 0, &res);
}
DM_ASSERT(res, *value = "");
if (arg6) {
char arg6_1[32] = "";
char arg6_1[128] = "";
strcpy(arg6_1, arg6);
char *opt = strchr(arg6_1, '.');
if (opt) {
@ -529,6 +558,23 @@ static void parse_mapping_obj(char *object, json_object *mapping, struct list_he
//Add to list
add_json_data_to_list(list, object, "uci", json_object_get_string(file), json_object_get_string(section_type), json_object_get_string(dmmap_file), "", "");
}
else if (strcmp(json_object_get_string(type), "ubus") == 0) {
//UBUS: arg1=type :: arg2=ubus_object :: arg3=ubus_method :: arg4=ubus_args1 :: arg5=ubus_args2 :: arg6=ubus_key
struct json_object *obj1, *method, *key, *args;
char *args1 = NULL;
json_object_object_get_ex(mapping, "ubus", &obj);
json_object_object_get_ex(obj, "object", &obj1);
json_object_object_get_ex(obj, "method", &method);
json_object_object_get_ex(obj, "args", &args);
json_object_object_foreach(args, arg1, args2) {
args1 = arg1;
}
json_object_object_get_ex(obj, "key", &key);
//Add to list
add_json_data_to_list(list, object, "ubus", json_object_get_string(obj1), json_object_get_string(method), args1, json_object_get_string(args2), json_object_get_string(key));
}
else {
//Add to list
add_json_data_to_list(list, object, "", "", "", "", "", "");

View file

@ -0,0 +1,298 @@
{
"Device.DSL.Line.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl",
"method": "status",
"args": {},
"key": "line"
}
},
"FirmwareVersion": {
"type": "string­",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "status",
"args": {},
"key": "firmware_version"
}
}
},
"UpstreamMaxBitRate": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "status",
"args": {},
"key": "max_bit_rate.us"
}
}
},
"Device.DSL.Line.{i}.Stats.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"TotalStart": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "total_start"
}
}
},
"ShowtimeStart": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "showtime_start"
}
}
},
"QuarterHourStart": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "quarter_hour_start"
}
}
},
"Device.DSL.Line.{i}.Stats.Total.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"ErroredSecs": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "total.errored_secs"
}
}
},
"SeverelyErroredSecs": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "total.severely_errored_secs"
}
}
}
},
"Device.DSL.Line.{i}.Stats.LastShowtime.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"ErroredSecs": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "lastshowtime.errored_secs"
}
}
},
"SeverelyErroredSecs": {
"type": "unsignedInt",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": false,
"mapping": {
"type": "ubus",
"ubus": {
"object": "dsl.line.@i-1",
"method": "stats",
"args": {},
"key": "lastshowtime.severely_errored_secs"
}
}
}
}
}
},
"Device.X_IOPSYS_EU_WiFiLife.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": false,
"Enable": {
"type": "boolean",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": {
"type": "uci",
"uci": {
"file": "wifilife",
"section": {
"type": "wifilife",
"name": "@wifilife[0]"
},
"option": {
"name": "enabled"
}
}
}
},
"Device.X_IOPSYS_EU_WiFiLife.Steering.{i}.": {
"type": "object",
"protocols": [
"cwmp",
"usp"
],
"array": true,
"mapping": {
"type": "uci",
"uci": {
"file": "wifilife",
"section": {
"type": "steer"
},
"dmmapfile": "dmmap_wifilife"
}
},
"Enable": {
"type": "boolean",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": {
"type": "uci",
"uci": {
"file": "wifilife",
"section": {
"type": "steer",
"index": "@i-1"
},
"option": {
"name": "enabled"
}
}
}
},
"LegacyFallback": {
"type": "boolean",
"protocols": [
"cwmp",
"usp"
],
"read": true,
"write": true,
"mapping": {
"type": "uci",
"uci": {
"file": "wifilife",
"section": {
"type": "steer",
"index": "@i-1"
},
"option": {
"name": "fallback_legacy"
}
}
}
}
}
}
}

View file

@ -1,23 +0,0 @@
LIB_EXAMPLE := lib/libexample.so
OBJS := example.o
PROG_CFLAGS = $(CFLAGS) -fstrict-aliasing
PROG_LDFLAGS = $(LDFLAGS) -lbbfdm
FPIC := -fPIC
.PHONY: all
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
all: $(LIB_EXAMPLE)
$(LIB_EXAMPLE): $(OBJS)
$(shell mkdir -p lib)
$(CC) -shared -Wl,-soname,libexample.so $^ -o $@
clean:
rm -f *.o
rm -f $(LIB_EXAMPLE)