/*
 * datamodel.c: Datamodel plugin
 *
 * Copyright (C) 2021-2023 IOPSYS Software Solutions AB. All rights reserved.
 *
 * Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
 *
 * See LICENSE file for license related information.
 */

#include "datamodel.h"

#define MAX_ENV_VAR_BUFF 1620
#define MAX_ENV_VAR_NUM 5
#define MAX_ENV_KEY_LEN 64
#define MAX_ENV_VAL_LEN 256

/* ********** DynamicObj ********** */
DM_MAP_OBJ tDynamicObj[] = {
/* parentobj, nextobject, parameter */
{"Device.", tSWmodObj, NULL},
{0}
};

/*************************************************************
* ENTRY METHOD
*************************************************************/
static int browseSoftwareModulesExecEnvInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *res = NULL, *du_obj = NULL, *arrobj = NULL;
	char *inst = NULL;
	int env = 0;
	struct dm_data data = {0};

	dmubus_call("swmodules", "ee_list", UBUS_ARGS{0}, 0, &res);
	dmjson_foreach_obj_in_array(res, arrobj, du_obj, env, 1, "environment") {
		inst = dmjson_get_value(du_obj, 1, "eeid");
		if (inst) {
			data.json_object = du_obj;
			if (DM_LINK_INST_OBJ(dmctx, parent_node, &data, inst) == DM_STOP)
				break;
		}
	}
	return 0;
}

static int browseSoftwareModulesDeploymentUnitInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *res = NULL, *du_obj = NULL, *arrobj = NULL;
	char *inst = NULL;
	int id = 0, du = 0;
	struct dm_data data = {0};

	dmubus_call("swmodules", "du_list", UBUS_ARGS{0}, 0, &res);
	dmjson_foreach_obj_in_array(res, arrobj, du_obj, du, 1, "deployment_unit") {
		data.json_object = du_obj;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &data, inst) == DM_STOP)
			break;
	}
	return 0;
}

static int browseSoftwareModulesExecutionUnitInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	json_object *res = NULL, *eu_obj = NULL, *arrobj = NULL;
	char *inst = NULL;
	int id = 0, eu = 0;
	struct dm_data data = {0};

	dmubus_call("swmodules", "eu_list", UBUS_ARGS{0}, 0, &res);
	dmjson_foreach_obj_in_array(res, arrobj, eu_obj, eu, 1, "execution_unit") {
		data.json_object = eu_obj;
		inst = handle_instance_without_section(dmctx, parent_node, ++id);
		if (DM_LINK_INST_OBJ(dmctx, parent_node, &data, inst) == DM_STOP)
			break;
	}
	return 0;
}

/*************************************************************
* GET & SET PARAM
*************************************************************/
static int get_SoftwareModules_ExecEnvNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *res = NULL, *environment = NULL;
	size_t nbre_env = 0;

	dmubus_call("swmodules", "ee_list", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, dmasprintf(value, "0"));
	json_object_object_get_ex(res, "environment", &environment);
	nbre_env = (environment) ? json_object_array_length(environment) : 0;
	dmasprintf(value, "%d", nbre_env);
	return 0;
}

static int get_SoftwareModules_DeploymentUnitNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *res = NULL, *deployment_unit = NULL;
	size_t nbre_du = 0;

	dmubus_call("swmodules", "du_list", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, dmasprintf(value, "0"));
	json_object_object_get_ex(res, "deployment_unit", &deployment_unit);
	nbre_du = (deployment_unit) ? json_object_array_length(deployment_unit) : 0;
	dmasprintf(value, "%d", nbre_du);
	return 0;
}

static int get_SoftwareModules_ExecutionUnitNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *res = NULL, *execution_unit = NULL;
	size_t nbre_env = 0;

	dmubus_call("swmodules", "eu_list", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, dmasprintf(value, "0"));
	json_object_object_get_ex(res, "execution_unit", &execution_unit);
	nbre_env = (execution_unit) ? json_object_array_length(execution_unit) : 0;
	dmasprintf(value, "%d", nbre_env);
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.Enable!UBUS:swmodules/environment//environment[i-1].autoboot*/
static int get_SoftwareModulesExecEnv_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "autoboot");
	return 0;
}

static int set_SoftwareModulesExecEnv_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *env_name = NULL;
	struct dm_data *p = NULL;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			p = (struct dm_data *)data;
			env_name = dmjson_get_value(p->json_object, 1, "ee_name");

			dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
				{"ee_name", env_name, String},
				{"parameter", "ee_enable", String},
				{"value", value, String}},
				3);
			break;
	}
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.Status!UBUS:swmodules/environment//environment[i-1].status*/
static int get_SoftwareModulesExecEnv_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "status");
	return 0;
}

static int get_SoftwareModulesExecEnv_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "0");
	return 0;
}

static int set_SoftwareModulesExecEnv_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return 0;
}

static int get_SoftwareModulesExecEnv_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *alias = dmjson_get_value(p->json_object, 1, "ee_alias");

	if (DM_STRLEN(alias) == 0)
		dmasprintf(value, "cpe-%s", instance);
	else
		dmasprintf(value, "%s", alias);

	return 0;
}

static int set_SoftwareModulesExecEnv_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ee_name = NULL;
	struct dm_data *p = NULL;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			p = (struct dm_data *)data;
			ee_name = dmjson_get_value(p->json_object, 1, "ee_name");

			if (DM_STRLEN(ee_name) == 0)
				return 0;

			dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
					{"ee_name", ee_name, String},
					{"parameter", "ee_alias", String},
					{"value", value, String}},
					3);

			break;
	}
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.Name!UBUS:swmodules/environment//environment[i-1].name*/
static int get_SoftwareModulesExecEnv_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "ee_name");
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.Type!UBUS:swmodules/environment//environment[i-1].type*/
static int get_SoftwareModulesExecEnv_Type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "type");
	return 0;
}

static int get_SoftwareModulesExecEnv_InitialRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "0");
	return 0;
}

static int set_SoftwareModulesExecEnv_InitialRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return 0;
}

static int get_SoftwareModulesExecEnv_RequestedRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "-1");
	return 0;
}

static int set_SoftwareModulesExecEnv_RequestedRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return 0;
}

static int get_SoftwareModulesExecEnv_CurrentRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "-1");
	return 0;
}

static int get_SoftwareModulesExecEnv_InitialExecutionUnitRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "-1");
	return 0;
}

static int set_SoftwareModulesExecEnv_InitialExecutionUnitRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.Vendor!UBUS:swmodules/environment//environment[i-1].vendor*/
static int get_SoftwareModulesExecEnv_Vendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "vendor");
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.Version!UBUS:swmodules/environment//environment[i-1].version*/
static int get_SoftwareModulesExecEnv_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "version");
	return 0;
}

static int get_SoftwareModulesExecEnv_ParentExecEnv(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *eid = dmjson_get_value(p->json_object, 1, "parent_ee_ref");

	if (eid == NULL || strcmp(eid, "0") == 0) {
		dmasprintf(value, "");
	} else {
		dmasprintf(value, "Device.SoftwareModules.ExecEnv.%s", eid);
	}

	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.AllocatedDiskSpace!UBUS:swmodules/environment//environment[i-1].allocateddiskspace*/
static int get_SoftwareModulesExecEnv_AllocatedDiskSpace(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "allocated_disk_space");
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.AvailableDiskSpace!UBUS:swmodules/environment//environment[i-1].availablediskspace*/
static int get_SoftwareModulesExecEnv_AvailableDiskSpace(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "available_disk_space");
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.AllocatedMemory!UBUS:swmodules/environment//environment[i-1].allocatedmemory*/
static int get_SoftwareModulesExecEnv_AllocatedMemory(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "allocated_memory");
	return 0;
}

/*#Device.SoftwareModules.ExecEnv.{i}.AvailableMemory!UBUS:swmodules/environment//environment[i-1].availablememory*/
static int get_SoftwareModulesExecEnv_AvailableMemory(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "available_memory");
	return 0;
}

#if 0
int get_SoftwareModulesExecEnv_ActiveExecutionUnits(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *res = NULL, *du_obj = NULL, *arrobj = NULL;
	char eu_list[2048];
	unsigned pos = 0;
	int eu = 0;

	eu_list[0] = 0;
	char *curr_env = dmjson_get_value((json_object *)data, 1, "ee_name");
	dmubus_call("swmodules", "eu_list", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, dmasprintf(value, ""));
	dmjson_foreach_obj_in_array(res, arrobj, du_obj, eu, 1, "execution_unit") {
		char *environment = dmjson_get_value(du_obj, 1, "ee_name");

		if (strcmp(environment, curr_env) == 0)
			pos += snprintf(&eu_list[pos], sizeof(eu_list) - pos, "Device.SoftwareModules.ExecutionUnit.%d,", eu+1);
	}

	if (pos)
		eu_list[pos - 1] = 0;

	*value = dmstrdup(eu_list);
	return 0;
}
#endif

/*#Device.SoftwareModules.DeploymentUnit.{i}.UUID!UBUS:swmodules/du_list//deployment_unit[i-1].uuid*/
static int get_SoftwareModulesDeploymentUnit_UUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "uuid");
	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.DUID!UBUS:swmodules/du_list//deployment_unit[i-1].duid*/
static int get_SoftwareModulesDeploymentUnit_DUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "duid");
	return 0;
}

static int get_SoftwareModulesDeploymentUnit_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *alias = dmjson_get_value(p->json_object, 1, "du_alias");

	if (DM_STRLEN(alias) == 0)
		dmasprintf(value, "cpe-%s", instance);
	else
		dmasprintf(value, "%s", alias);

	return 0;
}

static int set_SoftwareModulesDeploymentUnit_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *ee_name = NULL, *uuid = NULL;
	struct dm_data *p = NULL;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			p = (struct dm_data *)data;
			ee_name = dmjson_get_value(p->json_object, 1, "ee_name");
			uuid = dmjson_get_value(p->json_object, 1, "uuid");

			if (DM_STRLEN(ee_name) == 0 || DM_STRLEN(uuid) == 0)
				return 0;

			dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
					{"ee_name", ee_name, String},
					{"uuid", uuid, String},
					{"parameter", "du_alias", String},
					{"value", value, String}},
					4);

			break;
	}
	return 0;
}

static int get_SoftwareModulesExecutionUnit_RequestedState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "state");
	return 0;
}

static int set_SoftwareModulesExecutionUnit_RequestedState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *eid = NULL, *name = NULL;
	struct dm_data *p = NULL;

	switch (action)	{
		case VALUECHECK:
			if (strcmp(value, "Idle") != 0 && strcmp(value, "Active") != 0)
				return FAULT_9007;
			break;
		case VALUESET:
			p = (struct dm_data *)data;
			eid = dmjson_get_value(p->json_object, 1, "eeid");
			name = dmjson_get_value(p->json_object, 1, "eu_name");

			if (eid == NULL || name == NULL) {
				return 0;
			}

			if (eid[0] == '\0' || name[0] == '\0') {
				return 0;
			}

			dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
					{"eeid", eid, Integer},
					{"eu_name", name, String},
					{"parameter", "eu_requested_state", String},
					{"value", value, String}},
					4);

			break;
	}

	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.Name!UBUS:swmodules/du_list//deployment_unit[i-1].name*/
static int get_SoftwareModulesDeploymentUnit_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "du_name");
	return 0;
}

static int get_SoftwareModulesDeploymentUnit_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *val = dmjson_get_value(p->json_object, 1, "du_status");

	if (val) {
		char *tmp = strchr(val, '_');
		if (tmp)
			*tmp = '\0';

		dmasprintf(value, val);
	} else {
		dmasprintf(value, "");
	}

	return 0;
}

static int get_SoftwareModulesDeploymentUnit_Resolved(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *val = dmjson_get_value(p->json_object, 1, "du_status");

	if (DM_STRCMP(val, "Installed") == 0)
		dmasprintf(value, "1");
	else
		dmasprintf(value, "0");

	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.URL!UBUS:swmodules/du_list//deployment_unit[i-1].url*/
static int get_SoftwareModulesDeploymentUnit_URL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "url");
	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.Description!UBUS:swmodules/du_list//deployment_unit[i-1].description*/
static int get_SoftwareModulesDeploymentUnit_Description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "description");
	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.Vendor!UBUS:swmodules/du_list//deployment_unit[i-1].vendor*/
static int get_SoftwareModulesDeploymentUnit_Vendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "vendor");
	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.Version!UBUS:swmodules/du_list//deployment_unit[i-1].version*/
static int get_SoftwareModulesDeploymentUnit_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "version");
	return 0;
}

static int get_SoftwareModulesDeploymentUnit_VendorLogList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "");
	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.VendorConfigList!UBUS:swmodules/du_list//deployment_unit[i-1].config*/
static int get_SoftwareModulesDeploymentUnit_VendorConfigList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "");
	return 0;
}

static int get_SoftwareModulesDeploymentUnit_ExecutionUnitList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char eu_label[65] = {0};
	struct dm_data *p = (struct dm_data *)data;

	char *ee = dmjson_get_value(p->json_object, 1, "ee_name");
	char *eu = dmjson_get_value(p->json_object, 1, "eu_name");

	snprintf(eu_label, sizeof(eu_label), "%.32s%.32s", ee ? ee : "", eu ? eu : "");
	_bbfdm_get_references(ctx, "Device.SoftwareModules.ExecutionUnit.", "ExecEnvLabel", eu_label, value);

	return 0;
}

/*#Device.SoftwareModules.DeploymentUnit.{i}.ExecutionEnvRef!UBUS:swmodules/du_list//deployment_unit[i-1].environment*/
static int get_SoftwareModulesDeploymentUnit_ExecutionEnvRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *eid = dmjson_get_value(p->json_object, 1, "eeid");

	dmasprintf(value, "Device.SoftwareModules.ExecEnv.%s", eid);
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.EUID!UBUS:swmodules/eu_list//execution_unit[i-1].euid*/
static int get_SoftwareModulesExecutionUnit_EUID(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "euid");
	return 0;
}

static int get_SoftwareModulesExecutionUnit_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *alias = dmjson_get_value(p->json_object, 1, "eu_alias");

	if (DM_STRLEN(alias) == 0)
		dmasprintf(value, "cpe-%s", instance);
	else
		dmasprintf(value, "%s", alias);

	return 0;
}

static int set_SoftwareModulesExecutionUnit_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *eu_name = NULL, *eu_env = NULL;
	struct dm_data *p = NULL;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			p = (struct dm_data *)data;
			eu_name = dmjson_get_value(p->json_object, 1, "eu_name");
			eu_env = dmjson_get_value(p->json_object, 1, "ee_name");

			if (DM_STRLEN(eu_name) == 0 || DM_STRLEN(eu_env) == 0)
				return 0;

			dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
					{"ee_name", eu_env, String},
					{"eu_name", eu_name, String},
					{"parameter", "eu_alias", String},
					{"value", value, String}},
					4);

			break;
	}
	return 0;
}

static int set_SoftwareModulesExecutionUnit_AutoStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *eeid = NULL, *eu_name = NULL;
	struct dm_data *p = NULL;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			p = (struct dm_data *)data;
			eeid = dmjson_get_value(p->json_object, 1, "eeid");
			eu_name = dmjson_get_value(p->json_object, 1, "eu_name");

			if (eu_name == NULL || eeid == NULL) {
				return 0;
			}

			if (eu_name[0] == '\0' || eeid[0] == '\0') {
				return 0;
			}

			dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
					{"eeid", eeid, Integer},
					{"eu_name", eu_name, String},
					{"parameter", "eu_autostart", String},
					{"value", value, String}},
					4);

			break;
	}

	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.Name!UBUS:swmodules/eu_list//execution_unit[i-1].name*/
static int get_SoftwareModulesExecutionUnit_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "eu_name");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.ExecEnvLabel!UBUS:swmodules/eu_list//execution_unit[i-1].euid*/
static int get_SoftwareModulesExecutionUnit_ExecEnvLabel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *ee_name = NULL, *eu_name = NULL;
	struct dm_data *p = (struct dm_data *)data;

	ee_name = dmjson_get_value(p->json_object, 1, "ee_name");
	eu_name = dmjson_get_value(p->json_object, 1, "eu_name");

	dmasprintf(value, "%.32s%.32s", (ee_name)?(ee_name):"", (eu_name)?(eu_name):"");
	return 0;
}

static int get_SoftwareModulesExecutionUnit_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "state");
	return 0;
}

static int get_SoftwareModulesExecutionUnit_ExecutionFaultCode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "fault_code");
	return 0;
}

static int get_SoftwareModulesExecutionUnit_ExecutionFaultMessage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *fault = dmjson_get_value(p->json_object, 1, "fault_code");

	if (DM_STRCMP(fault, "FailureOnStart") == 0)
		dmasprintf(value, "Failed to start the OCI based Execution Unit");
	else
		dmasprintf(value, "");

	return 0;
}

static int get_SoftwareModulesExecutionUnit_AutoStart(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "autostart");
	return 0;
}

static int get_SoftwareModulesExecutionUnit_RunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "-1");
	return 0;
}

static int set_SoftwareModulesExecutionUnit_RunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.Vendor!UBUS:swmodules/eu_list//execution_unit[i-1].vendor*/
static int get_SoftwareModulesExecutionUnit_Vendor(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "vendor");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.Version!UBUS:swmodules/eu_list//execution_unit[i-1].version*/
static int get_SoftwareModulesExecutionUnit_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "version");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.Description!UBUS:swmodules/eu_list//execution_unit[i-1].description*/
static int get_SoftwareModulesExecutionUnit_Description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "description");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.DiskSpaceInUse!UBUS:swmodules/eu_list//execution_unit[i-1].disk_space*/
static int get_SoftwareModulesExecutionUnit_DiskSpaceInUse(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "disk_space");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.MemoryInUse!UBUS:swmodules/eu_list//execution_unit[i-1].memory_space*/
static int get_SoftwareModulesExecutionUnit_MemoryInUse(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	*value = dmjson_get_value(p->json_object, 1, "memory_space");
	return 0;
}

#if 0
int get_SoftwareModulesExecutionUnit_References(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	json_object *res = NULL, *du_obj = NULL, *arrobj = NULL;
	char *environment = NULL, *name = NULL;
	int du = 0;

	char *curr_name = dmjson_get_value((json_object *)data, 1, "eu_name");
	char *curr_environment = dmjson_get_value((json_object *)data, 1, "ee_name");

	dmubus_call("swmodules", "du_list", UBUS_ARGS{0}, 0, &res);
	DM_ASSERT(res, dmasprintf(value, ""));
	dmjson_foreach_obj_in_array(res, arrobj, du_obj, du, 1, "deployment_unit") {
		name = dmjson_get_value(du_obj, 1, "du_name");
		environment = dmjson_get_value(du_obj, 1, "ee_name");
		if ((name && curr_name && strcmp(name, curr_name) == 0) && (environment && curr_environment && strcmp(environment, curr_environment) == 0)) {
			dmasprintf(value, "Device.SoftwareModules.DeploymentUnit.%d", du+1);
			break;
		}
	}
	return 0;
}
#endif

static int get_SoftwareModulesExecutionUnit_AssociatedProcessList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *euid = dmjson_get_value(p->json_object, 1, "euid");

	if (DM_STRLEN(euid) == 0 || DM_STRCMP(euid, "Unknown") == 0)
		return 0;

	_bbfdm_get_references(ctx, "Device.DeviceInfo.ProcessStatus.Process.", "PID", euid, value);
	return 0;
}

static int get_SoftwareModulesExecutionUnit_VendorLogList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.VendorConfigList!UBUS:swmodules/eu_list//execution_unit[i-1].config*/
static int get_SoftwareModulesExecutionUnit_VendorConfigList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	dmasprintf(value, "");
	return 0;
}

/*#Device.SoftwareModules.ExecutionUnit.{i}.ExecutionEnvRef!UBUS:swmodules/eu_list//execution_unit[i-1].environment*/
static int get_SoftwareModulesExecutionUnit_ExecutionEnvRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *p = (struct dm_data *)data;
	char *eid = dmjson_get_value(p->json_object, 1, "eeid");

	dmasprintf(value, "Device.SoftwareModules.ExecEnv.%s", eid);
	return 0;
}

/*************************************************************
 * OPERATE COMMANDS
 *************************************************************/
static int operate_SoftwareModulesExecEnv_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return USP_FAULT_COMMAND_FAILURE;
}

static int operate_SoftwareModulesExecEnv_SetRunLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return USP_FAULT_COMMAND_FAILURE;
}

static operation_args softwaremodules_installdu_args = {
	.in = (const char *[]) {
		"URL",
		"UUID",
		"Username",
		"Password",
		"ExecutionEnvRef",
		"EnvVariable.{i}.Key",
		"EnvVariable.{i}.Value",
		NULL
	}
};

static int get_operate_args_SoftwareModules_InstallDU(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&softwaremodules_installdu_args;
	return 0;
}

static int operate_SoftwareModules_InstallDU(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	unsigned int eeid = 0;
	json_object *res = NULL;
	char env_var[MAX_ENV_VAR_BUFF] = {0};
	int i;

	char *url = dmjson_get_value((json_object *)value, 1, "URL");
	if (url[0] == '\0')
		return USP_FAULT_INVALID_ARGUMENT;

	for (i = 0; i < MAX_ENV_VAR_NUM; i++) {
		char buf[32] = {0};

		snprintf(buf, sizeof(buf), "EnvVariable.%d.Key", i+1);
		char *key = dmjson_get_value((json_object *)value, 1, buf);
		if (DM_STRLEN(key) == 0) {
			break;
		}

		snprintf(buf, sizeof(buf), "EnvVariable.%d.Value", i+1);
		char *val = dmjson_get_value((json_object *)value, 1, buf);

		if (DM_STRLEN(key) > MAX_ENV_KEY_LEN || DM_STRLEN(val) > MAX_ENV_VAL_LEN) {
			TRACE("Key value length exceeded, max key len=%d and value len=%d", MAX_ENV_KEY_LEN, MAX_ENV_VAL_LEN);
			bbfdm_set_fault_message(ctx, "Max supported key len=%d and value len=%d", MAX_ENV_KEY_LEN, MAX_ENV_VAL_LEN);
			return USP_FAULT_INVALID_ARGUMENT;
		}

		if ((DM_STRLEN(env_var) == 0) && ((sizeof(env_var) - 1) >= (DM_STRLEN(key) + DM_STRLEN(val) + 1))) {
			snprintf(env_var, sizeof(env_var), "%s=%s", key, val);
		} else if ((sizeof(env_var) - DM_STRLEN(env_var) - 1) >= (DM_STRLEN(key) + DM_STRLEN(val) + 2)) {
			char var[MAX_ENV_KEY_LEN + 2] = {0};

			snprintf(var, sizeof(var), "%s=", key);

			if (DM_STRSTR(env_var, var) == NULL) { // key should be unique
				char *tmp = env_var + DM_STRLEN(env_var);
				size_t size = sizeof(env_var) - DM_STRLEN(env_var);
				snprintf(tmp, size, ",%s=%s", key, val);
			}
		}
	}

	char *uuid = dmjson_get_value((json_object *)value, 1, "UUID");
	char *username = dmjson_get_value((json_object *)value, 1, "Username");
	char *password = dmjson_get_value((json_object *)value, 1, "Password");
	char *environment = dmjson_get_value((json_object *)value, 1, "ExecutionEnvRef");
	if (DM_STRLEN(environment) == 0) {
		eeid = 1;
	} else {
		sscanf(environment, "Device.SoftwareModules.ExecEnv.%u", &eeid);
	}

	if (eeid == 0)
		return USP_FAULT_COMMAND_FAILURE;

	char eeid_str[16] = {0};
	snprintf(eeid_str, sizeof(eeid_str), "%u", eeid);

	dmubus_call_timeout("swmodules", "du_install", UBUS_ARGS{
			{"url", url, String},
			{"uuid", uuid, String},
			{"username", username, String},
			{"password", password, String},
			{"eeid", eeid_str, Integer},
			{"env_var", env_var, String}},
			6,
			600000,
			&res);

	char *status = dmjson_get_value(res, 1, "status");
	return (strcmp(status, "true") == 0) ? 0 : USP_FAULT_COMMAND_FAILURE;
}

#if 0
static operation_args softwaremodulesdeploymentunit_update_args = {
	.in = (const char *[]) {
		"URL",
		"Username",
		"Password",
		NULL
	}
};

int get_operate_args_SoftwareModulesDeploymentUnit_Update(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&softwaremodulesdeploymentunit_update_args;
	return 0;
}

int operate_SoftwareModulesDeploymentUnit_Update(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	bool found = false;
	struct uci_section *s = NULL, *stmp = NULL;

	char *url = dmjson_get_value((json_object *)value, 1, "URL");
	if (url[0] == '\0')
		return USP_FAULT_INVALID_ARGUMENT;

	char *username = dmjson_get_value((json_object *)value, 1, "Username");
	char *password = dmjson_get_value((json_object *)value, 1, "Password");

	char *du_uuid = dmjson_get_value((json_object *)data, 1, "uuid");
	if (!du_uuid || du_uuid[0] == '\0')
		return USP_FAULT_COMMAND_FAILURE;

	// Find the uuid in config
	uci_foreach_sections_safe("swmodd", "du_eu_assoc", stmp, s) {
		char *val = NULL;
		dmuci_get_value_by_section_string(s, "uuid", &val);
		if (DM_STRCMP(du_uuid, val) == 0) {
			found = true;
			break;
		}
	}

	if (found == false)
		return USP_FAULT_COMMAND_FAILURE;

	dmuci_set_value_by_section(s, "new_url", url);
	dmuci_set_value_by_section(s, "username", username);
	dmuci_set_value_by_section(s, "password", password);
	dmuci_set_value_by_section(s, "du_status", "Updating");
	dmubus_call_set("uci", "commit", UBUS_ARGS{{"config", "swmodd", String}}, 1);

	return 0;
}
#endif

static int operate_SoftwareModulesDeploymentUnit_Uninstall(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	json_object *res = NULL;

	struct dm_data *p = (struct dm_data *)data;
	char *du_name = dmjson_get_value(p->json_object, 1, "du_name");
	char *eid = dmjson_get_value(p->json_object, 1, "eeid");

	dmubus_call_timeout("swmodules", "du_uninstall", UBUS_ARGS{
			{"du_name", du_name, String},
			{"eeid", eid, Integer},
			{"instance", instance, String}},
			3,
			600000,
			&res);

	char *status = dmjson_get_value(res, 1, "status");

	return (strcmp(status, "true") == 0) ? 0 : USP_FAULT_COMMAND_FAILURE;
}

static operation_args softwaremodulesexecutionunit_setrequestedstate_args = {
	.in = (const char *[]) {
		"RequestedState",
		NULL
	}
};

static int get_operate_args_SoftwareModulesExecutionUnit_SetRequestedState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&softwaremodulesexecutionunit_setrequestedstate_args;
	return 0;
}

static int operate_SoftwareModulesExecutionUnit_SetRequestedState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char *req_state = dmjson_get_value((json_object *)value, 1, "RequestedState");
	if (strcmp(req_state, "Idle") != 0 && strcmp(req_state, "Active") != 0)
		return USP_FAULT_INVALID_ARGUMENT;

	struct dm_data *p = (struct dm_data *)data;
	char *eid = dmjson_get_value(p->json_object, 1, "eeid");
	char *name = dmjson_get_value(p->json_object, 1, "eu_name");

	if (!eid || !name) {
		return USP_FAULT_COMMAND_FAILURE;
	}

	dmubus_call_set("swmodules", "set_config", UBUS_ARGS{
			{"eeid", eid, Integer},
			{"eu_name", name, String},
			{"parameter", "eu_requested_state", String},
			{"value", req_state, String}},
			4);

	return 0;
}

/*************************************************************
 * EVENTS
 *************************************************************/
static event_args du_state_change_args = {
	.name = "dustate.changed",
	.param = (const char *[]) {
		"UUID",
		"DeploymentUnitRef",
		"Version",
		"CurrentState",
		"Resolved",
		"ExecutionUnitRefList",
		"StartTime",
		"CompleteTime",
		"OperationPerformed",
		"Fault.FaultCode",
		"Fault.FaultString",
		NULL
	}
};

static int get_event_DUStateChagne(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = (char *)&du_state_change_args;
	return 0;
}

static int event_du_state_changed(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action) {
		case EVENT_CHECK:
			break;
		case EVENT_RUN:
		{
			char eu_refer[128] = {0};
			char du_refer[128] = {0};

			char *uuid = dmjson_get_value((json_object *)value, 1, "UUID");
			char *ver = dmjson_get_value((json_object *)value, 1, "Version");
			char *cur_state = dmjson_get_value((json_object *)value, 1, "CurrentState");
			char *resolved = dmjson_get_value((json_object *)value, 1, "Resolved");
			char *start = dmjson_get_value((json_object *)value, 1, "StartTime");
			char *end = dmjson_get_value((json_object *)value, 1, "CompleteTime");
			char *op = dmjson_get_value((json_object *)value, 1, "OperationPerformed");
			char *du_ref = dmjson_get_value((json_object *)value, 1, "DeploymentUnitRef");
			char *f_code = dmjson_get_value((json_object *)value, 1, "FaultCode");
			char *f_str = dmjson_get_value((json_object *)value, 1, "FaultString");

			if (DM_STRLEN(du_ref) == 0) {
				_bbfdm_get_references(ctx, "Device.SoftwareModules.DeploymentUnit.", "UUID", uuid, &du_ref);
			}

			if (DM_STRLEN(du_ref) != 0) {
				unsigned long inst = 0;

				snprintf(du_refer, sizeof(du_refer), "%s", du_ref);
				sscanf(du_ref, "Device.SoftwareModules.DeploymentUnit.%lu", &inst);

				if (inst != 0)
					snprintf(eu_refer, sizeof(eu_refer), "Device.SoftwareModules.ExecutionUnit.%lu", inst);
			}

			fill_blob_param(&ctx->bb, "UUID", uuid, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "DeploymentUnitRef", du_refer, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "Version", ver, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "CurrentState", cur_state, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "Resolved", resolved, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "StartTime", start, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "CompleteTime", end, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "OperationPerformed", op, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "ExecutionUnitRefList", eu_refer, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "Fault.FaultCode", f_code, DMT_TYPE[DMT_STRING], 0);
			fill_blob_param(&ctx->bb, "Fault.FaultString", f_str, DMT_TYPE[DMT_STRING], 0);
			break;
		}
	}

	return 0;
}

/**********************************************************************************************************************************
*                                            OBJ & PARAM DEFINITION
***********************************************************************************************************************************/
/* *** Device. *** */
DMOBJ tSWmodObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"SoftwareModules", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSoftwareModulesObj, tSoftwareModulesParams, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.SoftwareModules. *** */
DMOBJ tSoftwareModulesObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
{"ExecEnv", &DMREAD, NULL, NULL, NULL, browseSoftwareModulesExecEnvInst, NULL, NULL, NULL, tSoftwareModulesExecEnvParams, NULL, BBFDM_BOTH, NULL},
{"DeploymentUnit", &DMREAD, NULL, NULL, NULL, browseSoftwareModulesDeploymentUnitInst, NULL, NULL, NULL, tSoftwareModulesDeploymentUnitParams, NULL, BBFDM_BOTH, NULL},
{"ExecutionUnit", &DMREAD, NULL, NULL, NULL, browseSoftwareModulesExecutionUnitInst, NULL, NULL, NULL, tSoftwareModulesExecutionUnitParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tSoftwareModulesParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"ExecEnvNumberOfEntries", &DMREAD, DMT_UNINT, get_SoftwareModules_ExecEnvNumberOfEntries, NULL, BBFDM_BOTH},
{"DeploymentUnitNumberOfEntries", &DMREAD, DMT_UNINT, get_SoftwareModules_DeploymentUnitNumberOfEntries, NULL, BBFDM_BOTH},
{"ExecutionUnitNumberOfEntries", &DMREAD, DMT_UNINT, get_SoftwareModules_ExecutionUnitNumberOfEntries, NULL, BBFDM_BOTH},
{"InstallDU()", &DMASYNC, DMT_COMMAND, get_operate_args_SoftwareModules_InstallDU, operate_SoftwareModules_InstallDU, BBFDM_USP},
{"DUStateChange!", &DMREAD, DMT_EVENT, get_event_DUStateChagne, event_du_state_changed, BBFDM_USP},
{0}
};

/* *** Device.SoftwareModules.ExecEnv.{i}. *** */
DMLEAF tSoftwareModulesExecEnvParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"Enable", &DMWRITE, DMT_BOOL, get_SoftwareModulesExecEnv_Enable, set_SoftwareModulesExecEnv_Enable, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_Status, NULL, BBFDM_BOTH},
{"Reset", &DMWRITE, DMT_BOOL, get_SoftwareModulesExecEnv_Reset, set_SoftwareModulesExecEnv_Reset, BBFDM_CWMP},
{"Alias", &DMWRITE, DMT_STRING, get_SoftwareModulesExecEnv_Alias, set_SoftwareModulesExecEnv_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"Name", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_Name, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"Type", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_Type, NULL, BBFDM_BOTH},
{"InitialRunLevel", &DMWRITE, DMT_UNINT, get_SoftwareModulesExecEnv_InitialRunLevel, set_SoftwareModulesExecEnv_InitialRunLevel, BBFDM_BOTH},
{"RequestedRunLevel", &DMWRITE, DMT_INT, get_SoftwareModulesExecEnv_RequestedRunLevel, set_SoftwareModulesExecEnv_RequestedRunLevel, BBFDM_CWMP},
{"CurrentRunLevel", &DMREAD, DMT_INT, get_SoftwareModulesExecEnv_CurrentRunLevel, NULL, BBFDM_BOTH},
{"InitialExecutionUnitRunLevel", &DMWRITE, DMT_INT, get_SoftwareModulesExecEnv_InitialExecutionUnitRunLevel, set_SoftwareModulesExecEnv_InitialExecutionUnitRunLevel, BBFDM_BOTH},
{"Vendor", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_Vendor, NULL, BBFDM_BOTH},
{"Version", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_Version, NULL, BBFDM_BOTH},
{"ParentExecEnv", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_ParentExecEnv, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"AllocatedDiskSpace", &DMREAD, DMT_INT, get_SoftwareModulesExecEnv_AllocatedDiskSpace, NULL, BBFDM_BOTH},
{"AvailableDiskSpace", &DMREAD, DMT_INT, get_SoftwareModulesExecEnv_AvailableDiskSpace, NULL, BBFDM_BOTH},
{"AllocatedMemory", &DMREAD, DMT_INT, get_SoftwareModulesExecEnv_AllocatedMemory, NULL, BBFDM_BOTH},
{"AvailableMemory", &DMREAD, DMT_INT, get_SoftwareModulesExecEnv_AvailableMemory, NULL, BBFDM_BOTH},
//{"ActiveExecutionUnits", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_ActiveExecutionUnits, NULL, BBFDM_BOTH},
//{"ProcessorRefList", &DMREAD, DMT_STRING, get_SoftwareModulesExecEnv_ProcessorRefList, NULL, BBFDM_BOTH},
{"Reset()", &DMASYNC, DMT_COMMAND, NULL, operate_SoftwareModulesExecEnv_Reset, BBFDM_USP},
{"SetRunLevel()", &DMSYNC, DMT_COMMAND, NULL, operate_SoftwareModulesExecEnv_SetRunLevel, BBFDM_USP},
{0}
};

/* *** Device.SoftwareModules.DeploymentUnit.{i}. *** */
DMLEAF tSoftwareModulesDeploymentUnitParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"UUID", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_UUID, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER},
{"DUID", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_DUID, NULL, BBFDM_BOTH},
{"Alias", &DMWRITE, DMT_STRING, get_SoftwareModulesDeploymentUnit_Alias, set_SoftwareModulesDeploymentUnit_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"Name", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_Name, NULL, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_Status, NULL, BBFDM_BOTH},
{"Resolved", &DMREAD, DMT_BOOL, get_SoftwareModulesDeploymentUnit_Resolved, NULL, BBFDM_BOTH},
{"URL", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_URL, NULL, BBFDM_BOTH},
{"Description", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_Description, NULL, BBFDM_BOTH},
{"Vendor", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_Vendor, NULL, BBFDM_BOTH},
{"Version", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_Version, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"VendorLogList", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_VendorLogList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"VendorConfigList", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_VendorConfigList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"ExecutionUnitList", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_ExecutionUnitList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"ExecutionEnvRef", &DMREAD, DMT_STRING, get_SoftwareModulesDeploymentUnit_ExecutionEnvRef, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_REFERENCE},
//{"Update()", &DMASYNC, DMT_COMMAND, get_operate_args_SoftwareModulesDeploymentUnit_Update, operate_SoftwareModulesDeploymentUnit_Update, BBFDM_USP},
{"Uninstall()", &DMASYNC, DMT_COMMAND, NULL, operate_SoftwareModulesDeploymentUnit_Uninstall, BBFDM_USP},
{0}
};

DMLEAF tSoftwareModulesExecutionUnitParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/
{"EUID", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_EUID, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"Alias", &DMWRITE, DMT_STRING, get_SoftwareModulesExecutionUnit_Alias, set_SoftwareModulesExecutionUnit_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"Name", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_Name, NULL, BBFDM_BOTH},
{"ExecEnvLabel", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_ExecEnvLabel, NULL, BBFDM_BOTH, DM_FLAG_LINKER},
{"Status", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_Status, NULL, BBFDM_BOTH},
{"RequestedState", &DMWRITE, DMT_STRING, get_SoftwareModulesExecutionUnit_RequestedState, set_SoftwareModulesExecutionUnit_RequestedState, BBFDM_CWMP},
{"ExecutionFaultCode", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_ExecutionFaultCode, NULL, BBFDM_BOTH},
{"ExecutionFaultMessage", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_ExecutionFaultMessage, NULL, BBFDM_BOTH},
{"AutoStart", &DMWRITE, DMT_BOOL, get_SoftwareModulesExecutionUnit_AutoStart, set_SoftwareModulesExecutionUnit_AutoStart, BBFDM_BOTH},
{"RunLevel", &DMWRITE, DMT_UNINT, get_SoftwareModulesExecutionUnit_RunLevel, set_SoftwareModulesExecutionUnit_RunLevel, BBFDM_BOTH},
{"Vendor", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_Vendor, NULL, BBFDM_BOTH},
{"Version", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_Version, NULL, BBFDM_BOTH},
{"Description", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_Description, NULL, BBFDM_BOTH},
{"DiskSpaceInUse", &DMREAD, DMT_INT, get_SoftwareModulesExecutionUnit_DiskSpaceInUse, NULL, BBFDM_BOTH},
{"MemoryInUse", &DMREAD, DMT_INT, get_SoftwareModulesExecutionUnit_MemoryInUse, NULL, BBFDM_BOTH},
//{"References", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_References, NULL, BBFDM_BOTH},
{"AssociatedProcessList", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_AssociatedProcessList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"VendorLogList", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_VendorLogList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"VendorConfigList", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_VendorConfigList, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
//{"SupportedDataModelList", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_SupportedDataModelList, NULL, BBFDM_CWMP, DM_FLAG_REFERENCE},
{"ExecutionEnvRef", &DMREAD, DMT_STRING, get_SoftwareModulesExecutionUnit_ExecutionEnvRef, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"SetRequestedState()", &DMSYNC, DMT_COMMAND, get_operate_args_SoftwareModulesExecutionUnit_SetRequestedState, operate_SoftwareModulesExecutionUnit_SetRequestedState, BBFDM_USP},
{0}
};
