obuspa: Integrate v9.0.4

This commit is contained in:
Vivek Kumar Dutta 2025-01-08 09:10:50 +00:00 committed by IOPSYS Dev
parent 4ec80e072d
commit 82a5082538
No known key found for this signature in database
17 changed files with 426 additions and 557 deletions

View file

@ -1,3 +1,4 @@
if PACKAGE_obuspa
config OBUSPA_MTP_ENABLE_MQTT
bool "Enable MQTT as mtp protocol"
default y
@ -61,4 +62,4 @@ config OBUSPA_CWMP_DATAMODEL_SUPPORT
help
Expose Device.USPAgent., Device.STOMP., Device.MQTT.Client. objects over
ubus to make it available to bbfdm for CWMP access
endif

View file

@ -5,13 +5,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=obuspa
PKG_VERSION:=9.0.0.24
PKG_VERSION:=9.0.4.1
LOCAL_DEV:=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/obuspa.git
PKG_SOURCE_VERSION:=2d48b1525f7a2b72b61da6ce4cb306a6aa52d4c8
PKG_SOURCE_VERSION:=dc55cf10a8682c61b01acf45b9c0481173abbe5e
PKG_MAINTAINER:=Vivek Dutta <vivek.dutta@iopsys.eu>
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
@ -120,7 +120,6 @@ define Package/obuspa/install
$(INSTALL_DATA) ./files/etc/config/obuspa $(1)/etc/config/
$(INSTALL_DATA) ./files/etc/users/roles/*.json $(1)/etc/users/roles/
$(INSTALL_DATA) ./files/etc/obuspa/usp_utils.sh $(1)/etc/obuspa/
$(INSTALL_DATA) ./files/etc/obuspa/transient_dm.json $(1)/etc/obuspa/
echo "$(CONFIG_BBF_VENDOR_PREFIX)" > $(1)/etc/obuspa/vendor_prefix
$(INSTALL_BIN) ./files/etc/uci-defaults/01-fix-upgrade-uci $(1)/etc/uci-defaults/
$(INSTALL_BIN) ./files/etc/uci-defaults/60-generate-ctrust-defaults $(1)/etc/uci-defaults/

9
obuspa/Readme.md Normal file
View file

@ -0,0 +1,9 @@
# Obuspa patch management
As a part of obuspa integration, patch files used to manage changes in obuspa core files.
| Patch series | Remarks |
| ------------ | ------- |
| 00 - series | Up-streamable features/bugs |
| 10 - series | ubus-integration optimizations |
| 20 - series | deployment specific |

View file

@ -2,7 +2,7 @@ config obuspa 'global'
option enabled '1'
option debug '1'
option dhcp_discovery '1'
option log_level '2'
option log_level '3'
option prototrace '0'
option db_file '/etc/obuspa/usp.db'
#option max_group_sep '2'

View file

@ -1,5 +0,0 @@
{
"dmcaching_exclude": [
"Device.DeviceInfo.ProcessStatus.Process."
]
}

View file

@ -1,6 +1,8 @@
--- a/src/core/device_controller.c
+++ b/src/core/device_controller.c
@@ -4282,6 +4282,14 @@ int ProcessControllerAdded(int cont_inst
Index: obuspa-9.0.0.25/src/core/device_controller.c
===================================================================
--- obuspa-9.0.0.25.orig/src/core/device_controller.c
+++ obuspa-9.0.0.25/src/core/device_controller.c
@@ -4210,6 +4210,14 @@ int ProcessControllerAdded(int cont_inst
goto exit;
}
@ -15,7 +17,7 @@
// Exit if unable to get the object instance numbers present in this controller's MTP table
USP_SNPRINTF(path, sizeof(path), "%s.%d.MTP", device_cont_root, cont_instance);
err = DATA_MODEL_GetInstances(path, &iv);
@@ -4323,14 +4331,6 @@ int ProcessControllerAdded(int cont_inst
@@ -4251,14 +4259,6 @@ int ProcessControllerAdded(int cont_inst
DEVICE_MQTT_UpdateControllerTopics();
#endif

View file

@ -1,13 +0,0 @@
--- a/src/core/cli_server.c
+++ b/src/core/cli_server.c
@@ -785,10 +785,6 @@ int ExecuteCli_Get(char *arg1, char *arg
USP_ASSERT(gge->value != NULL);
SendCliResponse("%s => %s\n", gge->path, gge->value);
}
- else
- {
- SendCliResponse("ERROR: %d retrieving %s (%s)\n", gge->err_code, gge->path, gge->err_msg);
- }
}
GROUP_GET_VECTOR_Destroy(&ggv);

View file

@ -1,18 +1,21 @@
diff --git a/src/core/bdc_exec.c b/src/core/bdc_exec.c
index dc30a98..6a2938b 100644
--- a/src/core/bdc_exec.c
+++ b/src/core/bdc_exec.c
@@ -548,11 +548,19 @@ int StartSendingReport(bdc_connection_t
@@ -548,10 +548,25 @@ int StartSendingReport(bdc_connection_t *bc)
// Set the list of headers
bc->headers = NULL;
- bc->headers = curl_slist_append(bc->headers, "Content-Type: application/json; charset=UTF-8");
- if (bc->flags & BDC_FLAG_HEADER_OBJ_HIER)
- bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: NameValuePair");
+
+
+ if (bc->flags & BDC_FLAG_HEADER_OBJ_HIER) {
+ bc->headers = curl_slist_append(bc->headers, "Content-Type: application/json; charset=UTF-8");
bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: ObjectHierarchy");
- else
+ bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: ObjectHierarchy");
+ } else if (bc->flags & BDC_FLAG_HEADER_NAME_VAL) {
+ bc->headers = curl_slist_append(bc->headers, "Content-Type: application/json; charset=UTF-8");
bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: NameValuePair");
+ bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: NameValuePair");
+ } else if (bc->flags & BDC_FLAG_HEADER_PER_COL) {
+ bc->headers = curl_slist_append(bc->headers, "Content-Type: text/csv; charset=UTF-8");
+ bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: ParameterPerColumn");
@ -20,59 +23,69 @@
+ bc->headers = curl_slist_append(bc->headers, "Content-Type: text/csv; charset=UTF-8");
+ bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: ParameterPerRow");
+ }
+
if (bc->flags & BDC_FLAG_GZIP)
{
+ curl_easy_setopt(curl_ctx, CURLOPT_ACCEPT_ENCODING, "gzip");
bc->headers = curl_slist_append(bc->headers, "Content-Encoding: gzip");
}
diff --git a/src/core/bdc_exec.h b/src/core/bdc_exec.h
index 8c259c5..6322221 100644
--- a/src/core/bdc_exec.h
+++ b/src/core/bdc_exec.h
@@ -53,6 +53,9 @@ void BDC_EXEC_ScheduleExit(void);
@@ -53,6 +53,8 @@ void BDC_EXEC_ScheduleExit(void);
#define BDC_FLAG_PUT 0x00000001 // If set, HTTP PUT should be used instead of HTTP POST when sending the report to the BDC server
#define BDC_FLAG_GZIP 0x00000002 // If set, the reports contants are Gzipped
#define BDC_FLAG_DATE_HEADER 0x00000004 // If set, the date header should be included in the HTTP post.
-#define BDC_FLAG_HEADER_OBJ_HIER 0x00000008 // If set, report format in header would be ObjectHierarchy otherwise NameValuePair
-
-
+#define BDC_FLAG_HEADER_OBJ_HIER 0x00000008 // If set, report format in header would be json ObjectHierarchy
+#define BDC_FLAG_HEADER_NAME_VAL 0x00000010 // If set, report format in header would be json NameValuePair
+#define BDC_FLAG_HEADER_PER_ROW 0x00000020 // If set, report format in header would be csv ParameterPerRow
+#define BDC_FLAG_HEADER_PER_COL 0x00000040 // If set, report format in header would be csv ParameterPerColumn
#endif
diff --git a/src/core/device_bulkdata.c b/src/core/device_bulkdata.c
index 915b282..f799793 100755
--- a/src/core/device_bulkdata.c
+++ b/src/core/device_bulkdata.c
@@ -70,9 +70,12 @@
@@ -70,8 +70,12 @@
//------------------------------------------------------------------------------
// Definitions for formats that we support
-#define BULKDATA_ENCODING_TYPE "JSON"
-#define BULKDATA_JSON_REPORT_FORMAT "NameValuePair"
+#define BULKDATA_ENCODING_TYPE_JSON "JSON"
+#define BULKDATA_ENCODING_TYPE_CSV "CSV"
#define BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE "NameValuePair"
#define BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER "ObjectHierarchy"
+#define BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE "NameValuePair"
+#define BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER "ObjectHierarchy"
+#define BULKDATA_CSV_REPORT_FORMAT_PER_COLUMN "ParameterPerColumn"
+#define BULKDATA_CSV_REPORT_FORMAT_PER_ROW "ParameterPerRow"
// Definitions for Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp
@@ -156,6 +159,7 @@ static char *profile_push_event_args[] =
@@ -161,6 +165,7 @@ static char *profile_push_event_args[] =
typedef struct
{
int num_retained_failed_reports;
+ char encoding_type[10];
char report_timestamp[33];
char url[1025];
char username[257];
@@ -164,6 +168,11 @@ typedef struct
#ifdef ENABLE_MQTT
char mqtt_reference[254]; // relates to Device.BulkData.Profile.{i}.MQTT.Reference
char mqtt_publish_topic[254]; // relates to Device.BulkData.Profile.{i}.MQTT.PublishTopic
@@ -171,6 +176,12 @@ typedef struct
char password[257];
char compression[9];
char method[9];
bool use_date_header;
char report_format[20];
+ char report_format[20];
+ char field_separator[10];
+ char row_separator[10];
+ char escape_char[10];
+ char csv_format[20];
+ char row_timestamp[33];
bool use_date_header;
} profile_ctrl_params_t;
//------------------------------------------------------------------------------
@@ -211,6 +220,7 @@ int Validate_BulkDataEncodingType(dm_req
@@ -219,6 +230,7 @@ int Validate_BulkDataEncodingType(dm_req_t *req, char *value);
int Validate_BulkDataReportingInterval(dm_req_t *req, char *value);
int Validate_BulkDataReference(dm_req_t *req, char *value);
int Validate_BulkDataReportFormat(dm_req_t *req, char *value);
@ -80,25 +93,26 @@
int Validate_BulkDataReportTimestamp(dm_req_t *req, char *value);
int Validate_BulkDataCompression(dm_req_t *req, char *value);
int Validate_BulkDataHTTPMethod(dm_req_t *req, char *value);
@@ -239,6 +249,8 @@ bulkdata_profile_t *bulkdata_find_profil
@@ -246,7 +258,8 @@ bulkdata_profile_t *bulkdata_find_free_profile(void);
bulkdata_profile_t *bulkdata_find_profile(int profile_id);
int bulkdata_calc_report_map(bulkdata_profile_t *bp, kv_vector_t *report_map);
int bulkdata_reduce_to_alt_name(char *spec, char *path, char *alt_name, char *out_buf, int buf_len);
char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp, char *report_format);
+char *bulkdata_generate_csv_report(bulkdata_profile_t *bp, char *field_separator, char *row_separator,
+ char *escape_char, char *csv_format, char *row_timestamp);
-char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp);
+char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp, char *report_format);
+char *bulkdata_generate_csv_report(bulkdata_profile_t *bp, char *field_separator, char *row_separator, char *escape_char, char *csv_format, char *row_timestamp);
unsigned char *bulkdata_compress_report(profile_ctrl_params_t *ctrl, char *input_buf, int input_len, int *p_output_len);
int bulkdata_schedule_sending_http_report(profile_ctrl_params_t *ctrl, bulkdata_profile_t *bp, unsigned char *json_report, int report_len);
int bulkdata_start_profile(bulkdata_profile_t *bp);
@@ -253,6 +265,8 @@ char *bulkdata_platform_calc_uri_query_s
@@ -261,6 +274,8 @@ char *bulkdata_platform_calc_uri_query_string(kv_vector_t *escaped_map);
int bulkdata_platform_get_param_refs(int profile_id, param_ref_vector_t *param_refs);
void bulkdata_expand_param_ref(param_ref_entry_t *pr, group_get_vector_t *ggv);
void bulkdata_append_to_result_map(param_ref_entry_t *pr, group_get_vector_t *ggv, kv_vector_t *report_map);
+void append_string_to_target(char *str, char **output);
+char *csv_encode(const char *str);
/*********************************************************************//**
**
@@ -285,7 +299,7 @@ int DEVICE_BULKDATA_Init(void)
#ifdef ENABLE_MQTT
int Validate_BulkDataMqttReference(dm_req_t *req, char *value);
void bulkdata_process_profile_mqtt(bulkdata_profile_t *bp);
@@ -298,7 +313,7 @@ int DEVICE_BULKDATA_Init(void)
err |= USP_REGISTER_VendorParam_ReadOnly("Device.BulkData.Status", Get_BulkDataGlobalStatus, DM_STRING);
err |= USP_REGISTER_Param_Constant("Device.BulkData.MinReportingInterval", BULKDATA_MINIMUM_REPORTING_INTERVAL_STR, DM_UINT);
err |= USP_REGISTER_Param_SupportedList("Device.BulkData.Protocols", bdc_protocols, NUM_ELEM(bdc_protocols));
@ -107,7 +121,7 @@
err |= USP_REGISTER_Param_Constant("Device.BulkData.ParameterWildCardSupported", "true", DM_BOOL);
err |= USP_REGISTER_Param_Constant("Device.BulkData.MaxNumberOfProfiles", BULKDATA_MAX_PROFILES_STR, DM_INT);
err |= USP_REGISTER_Param_Constant("Device.BulkData.MaxNumberOfParameterReferences", "-1", DM_INT);
@@ -300,7 +314,7 @@ int DEVICE_BULKDATA_Init(void)
@@ -313,7 +328,7 @@ int DEVICE_BULKDATA_Init(void)
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.Name", "", NULL, NULL, DM_STRING);
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.NumberOfRetainedFailedReports", "0", Validate_NumberOfRetainedFailedReports, NULL, DM_INT);
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.Protocol", BULKDATA_PROTOCOL_HTTP, Validate_BulkDataProtocol, NULL, DM_STRING);
@ -116,8 +130,12 @@
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.ReportingInterval", "86400", Validate_BulkDataReportingInterval, NotifyChange_BulkDataReportingInterval, DM_UINT);
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.TimeReference", UNKNOWN_TIME_STR, NULL, NotifyChange_BulkDataTimeReference, DM_DATETIME);
@@ -315,6 +329,13 @@ int DEVICE_BULKDATA_Init(void)
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportFormat", BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE, Validate_BulkDataReportFormat, NULL, DM_STRING);
@@ -325,9 +340,16 @@ int DEVICE_BULKDATA_Init(void)
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.Parameter.{i}.Reference", "", Validate_BulkDataReference, NULL, DM_STRING);
// Device.BulkData.Profile.{i}.JSONEncoding
- err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportFormat", BULKDATA_JSON_REPORT_FORMAT, Validate_BulkDataReportFormat, NULL, DM_STRING);
+ err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportFormat", BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE, Validate_BulkDataReportFormat, NULL, DM_STRING);
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp", BULKDATA_JSON_TIMESTAMP_FORMAT_EPOCH, Validate_BulkDataReportTimestamp, NULL, DM_STRING);
+ // Device.BulkData.Profile.{i}.CSVEncoding
@ -130,23 +148,37 @@
// Device.BulkData.Profile.{i}.HTTP
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.HTTP.URL", "", NULL, NotifyChange_BulkDataURL, DM_STRING);
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.HTTP.Username", "", NULL, NULL, DM_STRING);
@@ -594,9 +615,10 @@ int Validate_BulkDataProtocol(dm_req_t *
@@ -613,9 +635,10 @@ int Validate_BulkDataProtocol(dm_req_t *req, char *value)
int Validate_BulkDataEncodingType(dm_req_t *req, char *value)
{
// Exit if trying to set a value outside of the range we accept
- if (strcmp(value, BULKDATA_ENCODING_TYPE) != 0)
+ if (strcmp(value, BULKDATA_ENCODING_TYPE_JSON) != 0 && strcmp(value, BULKDATA_ENCODING_TYPE_CSV) != 0)
{
- {
- USP_ERR_SetMessage("%s: Only EncodingType supported is '%s'", __FUNCTION__, BULKDATA_ENCODING_TYPE);
+ if (strcmp(value, BULKDATA_ENCODING_TYPE_JSON) != 0 && strcmp(value, BULKDATA_ENCODING_TYPE_CSV) != 0)
+ {
+ USP_ERR_SetMessage("%s: Only EncodingType supported are '%s,%s'", __FUNCTION__,
+ BULKDATA_ENCODING_TYPE_JSON, BULKDATA_ENCODING_TYPE_CSV);
return USP_ERR_INVALID_VALUE;
}
@@ -713,6 +735,32 @@ int Validate_BulkDataReportFormat(dm_req
/*********************************************************************//**
**
@@ -719,9 +742,36 @@ int Validate_BulkDataReference(dm_req_t *req, char *value)
int Validate_BulkDataReportFormat(dm_req_t *req, char *value)
{
// Exit if trying to set a value outside of the range we accept
- if (strcmp(value, BULKDATA_JSON_REPORT_FORMAT) != 0)
+ if (strcmp(value, BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE) != 0 &&
+ strcmp(value, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) != 0)
+ {
+ USP_ERR_SetMessage("%s: Supported JSON Report Formats are '%s', '%s'", __FUNCTION__, BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER);
+ return USP_ERR_INVALID_VALUE;
+ }
+
+ return USP_ERR_OK;
+}
+
+/*********************************************************************//**
+**
+** Validate_BulkDataCSVReportFormat
+**
+** Validates Device.BulkData.Profile.{i}.CSVEncoding.ReportFormat
@ -162,21 +194,14 @@
+ // Exit if trying to set a value outside of the range we accept
+ if (strcmp(value, BULKDATA_CSV_REPORT_FORMAT_PER_COLUMN) != 0 &&
+ strcmp(value, BULKDATA_CSV_REPORT_FORMAT_PER_ROW) != 0)
+ {
{
- USP_ERR_SetMessage("%s: Only JSON Report Format supported is '%s'", __FUNCTION__, BULKDATA_JSON_REPORT_FORMAT);
+ USP_ERR_SetMessage("%s: Only JSON Report Format supported are '%s', '%s'", __FUNCTION__,
+ BULKDATA_CSV_REPORT_FORMAT_PER_COLUMN, BULKDATA_CSV_REPORT_FORMAT_PER_ROW);
+ return USP_ERR_INVALID_VALUE;
+ }
+
+ return USP_ERR_OK;
+}
+
+/*********************************************************************//**
+**
** Validate_BulkDataReportTimestamp
**
** Validates Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp
@@ -2004,6 +2052,14 @@ int bulkdata_platform_get_profile_contro
return USP_ERR_INVALID_VALUE;
}
@@ -2052,6 +2102,14 @@ int bulkdata_platform_get_profile_control_params(bulkdata_profile_t *bp, profile
return err;
}
@ -191,7 +216,7 @@
// Exit if unable to get ReportTimestamp
USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.JSONEncoding.ReportTimestamp", bp->profile_id);
err = DATA_MODEL_GetParameterValue(path, ctrl_params->report_timestamp, sizeof(ctrl_params->report_timestamp), 0);
@@ -2020,6 +2076,46 @@ int bulkdata_platform_get_profile_contro
@@ -2060,6 +2118,54 @@ int bulkdata_platform_get_profile_control_params(bulkdata_profile_t *bp, profile
return err;
}
@ -235,10 +260,18 @@
+ return err;
+ }
+
return USP_ERR_OK;
}
@@ -2256,7 +2352,7 @@ void bulkdata_process_profile_http(bulkd
+ // Exit if unable to get ReportFormat
+ USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.JSONEncoding.ReportFormat", bp->profile_id);
+ err = DATA_MODEL_GetParameterValue(path, ctrl_params->report_format, sizeof(ctrl_params->report_format), 0);
+ if (err != USP_ERR_OK)
+ {
+ return err;
+ }
+
#ifdef ENABLE_MQTT
{
char protocol[32];
@@ -2333,7 +2439,7 @@ void bulkdata_process_profile_http(bulkdata_profile_t *bp)
{
int err;
report_t *cur_report;
@ -247,11 +280,11 @@
profile_ctrl_params_t ctrl;
unsigned char *compressed_report;
int compressed_len;
@@ -2295,10 +2391,23 @@ void bulkdata_process_profile_http(bulkd
@@ -2372,10 +2478,23 @@ void bulkdata_process_profile_http(bulkdata_profile_t *bp)
}
// Exit if unable to generate the report
- json_report = bulkdata_generate_json_report(bp, ctrl.report_timestamp, ctrl.report_format);
- json_report = bulkdata_generate_json_report(bp, ctrl.report_timestamp);
- if (json_report == NULL)
- {
- USP_ERR_SetMessage("%s: bulkdata_generate_json_report failed", __FUNCTION__);
@ -275,7 +308,7 @@
return;
}
@@ -2307,14 +2416,14 @@ void bulkdata_process_profile_http(bulkd
@@ -2384,14 +2503,14 @@ void bulkdata_process_profile_http(bulkdata_profile_t *bp)
USP_LOG_Info("BULK DATA: using compression method=%s", ctrl.compression);
if (enable_protocol_trace)
{
@ -294,15 +327,15 @@
}
// NOTE: From this point on, only the compressed_report exists
@@ -2344,9 +2453,15 @@ void bulkdata_process_profile_usp_event(
@@ -2421,8 +2540,15 @@ void bulkdata_process_profile_usp_event(bulkdata_profile_t *bp)
kv_vector_t event_args;
kv_pair_t kv;
report_t *cur_report;
- char *json_report;
char report_timestamp[33];
+ char report_format[20];
+ char *report;
+ char encoding_type[10] = {0};
char report_timestamp[33] = {0};
char report_format[20] = {0};
+ char field_separator[10];
+ char row_separator[10];
+ char escape_char[10];
@ -311,7 +344,7 @@
// Exit if the MTP has not been connected to successfully after bootup
// This is to prevent BDC events being enqueued before the Boot! event is sent (the Boot! event is only sent after successfully connecting to the MTP).
@@ -2355,20 +2470,62 @@ void bulkdata_process_profile_usp_event(
@@ -2431,13 +2557,63 @@ void bulkdata_process_profile_usp_event(bulkdata_profile_t *bp)
goto exit;
}
@ -320,19 +353,15 @@
- err = DATA_MODEL_GetParameterValue(path, report_timestamp, sizeof(report_timestamp), 0);
- if (err != USP_ERR_OK)
- {
- return;
- }
+ // Exit if unable to get EncodingType
+ USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.EncodingType", bp->profile_id);
+ err = DATA_MODEL_GetParameterValue(path, encoding_type, sizeof(encoding_type), 0);
+ if (err != USP_ERR_OK) {
return;
}
- // Exit if unable to get ReportFormat
- USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.JSONEncoding.ReportFormat", bp->profile_id);
- err = DATA_MODEL_GetParameterValue(path, report_format, sizeof(report_format), 0);
- if (err != USP_ERR_OK)
- {
- return;
+ return;
+ }
+
+ if (strcmp(encoding_type, BULKDATA_ENCODING_TYPE_JSON) == 0) {
+ // Exit if unable to get ReportTimestamp
+ USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.JSONEncoding.ReportTimestamp", bp->profile_id);
@ -382,15 +411,14 @@
+ if (err != USP_ERR_OK) {
+ return;
+ }
}
+ }
// When sending via USP events, only one report is ever sent in each USP event
@@ -2388,10 +2545,16 @@ void bulkdata_process_profile_usp_event(
// So ensure all retained reports are removed. NOTE: Clearing the reports here is only necessary when switching protocol from HTTP to USP event, and where HTTP had some unsent reports
@@ -2455,11 +2631,17 @@ void bulkdata_process_profile_usp_event(bulkdata_profile_t *bp)
}
bp->num_retained_reports = 1;
// Exit if unable to generate the report
- json_report = bulkdata_generate_json_report(bp, report_timestamp, report_format);
- if (json_report == NULL)
+ if (strcmp(encoding_type, BULKDATA_ENCODING_TYPE_JSON) == 0) {
+ report = bulkdata_generate_json_report(bp, report_timestamp, report_format);
+ } else {
@ -398,14 +426,17 @@
+ csv_format, row_timestamp);
+ }
+
// Exit if unable to generate the report
- json_report = bulkdata_generate_json_report(bp, report_timestamp);
- if (json_report == NULL)
+ if (report == NULL)
{
- USP_ERR_SetMessage("%s: bulkdata_generate_json_report failed", __FUNCTION__);
+ USP_ERR_SetMessage("%s: bulkdata failed to generate report", __FUNCTION__);
+ USP_ERR_SetMessage("%s: bulkdata_generate_report failed", __FUNCTION__);
return;
}
@@ -2399,15 +2562,15 @@ void bulkdata_process_profile_usp_event(
@@ -2467,15 +2649,15 @@ void bulkdata_process_profile_usp_event(bulkdata_profile_t *bp)
// Construct event_args manually to avoid the overhead of a malloc and copy of the report in KV_VECTOR_Add()
kv.key = "Data";
@ -424,10 +455,194 @@
// From the point of view of this code, the report(s) have been successfully sent, so don't retain them
// NOTE: Sending of the reports successfully is delegated to the USP notification retry mechanism
@@ -2869,6 +3032,319 @@ char *bulkdata_generate_json_report(bulk
@@ -2547,7 +2729,7 @@ void bulkdata_process_profile_mqtt(bulkdata_profile_t *bp)
}
/*********************************************************************//**
// Exit if unable to generate the report
- report = bulkdata_generate_json_report(bp, ctrl.report_timestamp);
+ report = bulkdata_generate_json_report(bp, ctrl.report_timestamp, ctrl.report_format);
if (report == NULL)
{
USP_ERR_SetMessage("%s: bulkdata_generate_json_report failed", __FUNCTION__);
@@ -2762,7 +2944,7 @@ int bulkdata_reduce_to_alt_name(char *spec, char *path, char *alt_name, char *ou
** \return pointer to NULL terminated dynamically allocated buffer containing the serialized report to send
**
**************************************************************************/
-char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp)
+char *bulkdata_generate_json_name_value_pair_report(bulkdata_profile_t *bp, char *report_timestamp)
{
JsonNode *top; // top of report
JsonNode *array; // array of reports (retained + current)
@@ -2867,6 +3049,483 @@ char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timesta
return result;
}
+static char *create_json_obj_hier_report(bulkdata_profile_t *bp, char *report_timestamp)
+{
+ JsonNode *top; // top of report
+ JsonNode *array; // array of reports (retained + current)
+ JsonNode *element; // element of json array, containing an individual report
+ JsonNode *temp;
+ char *param_path;
+ char *param_type_value;
+ char param_type;
+ char *param_value;
+ kv_vector_t *report_map;
+ report_t *report;
+ double value_as_number;
+ long long value_as_ll;
+ unsigned long long value_as_ull;
+ bool value_as_bool;
+ int i, j;
+ char buf[32];
+ kv_pair_t *kv;
+ int err;
+ char *result;
+
+ top = json_mkobject();
+ array = json_mkarray();
+
+ // Iterate over all reports adding them to the JSON array
+ for (i=0; i < bp->num_retained_reports; i++)
+ {
+ report = &bp->reports[i];
+ report_map = &report->report_map;
+
+ // Add Collection time to each json report element (only if specified and not 'None')
+ element = json_mkobject();
+ if (strcmp(report_timestamp, "Unix-Epoch")==0)
+ {
+ json_append_member(element, "CollectionTime", json_mknumber(report->collection_time));
+ }
+ else if (strcmp(report_timestamp, "ISO-8601")==0)
+ {
+ result = iso8601_from_unix_time(report->collection_time, buf, sizeof(buf));
+ if (result != NULL)
+ {
+ json_append_member(element, "CollectionTime", json_mkstring(buf));
+ }
+ }
+
+ temp = element;
+ // Iterate over each parameter, adding it to the json element. Take account of the parameter's type
+ for (j=0; j < report_map->num_entries; j++)
+ {
+ char buff[2056] = {0};
+ char *pch = NULL, *pchr = NULL, *argv[128] = {0};
+ int n = 0;
+
+ kv = &report_map->vector[j];
+ param_path = kv->key;
+ param_type_value = kv->value;
+ param_type = param_type_value[0]; // First character denotes the type of the parameter
+ param_value = &param_type_value[1]; // Subsequent characters contain the parameter's value
+
+ strncpy(buff, param_path, sizeof(buff));
+ for (pch = strtok_r(buff, ".", &pchr); pch != NULL; pch = strtok_r(NULL, ".", &pchr)) {
+ int idx;
+ JsonNode *obj = element;
+ argv[n] = pch;
+
+ for (idx = 0; idx <= n; idx++) {
+ if (obj == NULL)
+ break;
+ obj = json_find_member(obj, argv[idx]);
+ }
+
+ if (obj)
+ temp = obj;
+ else {
+ if (pchr != NULL && *pchr != '\0') {
+ // It is a DMOBJ
+ JsonNode *new = json_mkobject();
+ json_append_member(temp, pch, new);
+ temp = new;
+ } else {
+ // It is a DMPARAM
+ switch (param_type)
+ {
+ case 'S':
+ json_append_member(temp, pch, json_mkstring(param_value) );
+ break;
+
+ case 'U':
+ value_as_ull = strtoull(param_value, NULL, 10);
+ json_append_member(temp, pch, json_mkulonglong(value_as_ull) );
+ break;
+
+ case 'L':
+ value_as_ll = strtoll(param_value, NULL, 10);
+ json_append_member(temp, pch, json_mklonglong(value_as_ll) );
+ break;
+
+ case 'N':
+ value_as_number = atof(param_value);
+ json_append_member(temp, pch, json_mknumber(value_as_number) );
+ break;
+
+ case 'B':
+ err = TEXT_UTILS_StringToBool(param_value, &value_as_bool);
+ if (err == USP_ERR_OK)
+ {
+ json_append_member(temp, pch, json_mkbool(value_as_bool) );
+ }
+ break;
+
+ default:
+ USP_ERR_SetMessage("%s: Invalid JSON parameter type ('%c') in report map for %s", __FUNCTION__, param_type_value[0], param_path);
+ break;
+ }
+ }
+ }
+ n++;
+ }
+ }
+
+ // Add the json element to the json array
+ json_append_element(array, element);
+ }
+
+ // Finally add the array to the report top level
+ json_append_member(top, "Report", array);
+
+ // Serialize the JSON tree
+ result = json_stringify(top, " ");
+
+ // Clean up the JSON tree
+ json_delete(top); // Other JsonNodes which are children of this top level tree will be deleted
+
+ return result;
+}
+
+/*********************************************************************//**
+**
+** bulkdata_generate_json_report
+**
+** Generates a JSON name-value pair or object-hierarchy format report
+** NOTE: The report contains all retained failed reports, as well as the current report
+** See TR-157 section A.4.2 (end) for an example, and section A.3.5.2 for layout of content containing failed report transmissions
+**
+** \param bp - pointer to bulk data profile containing all reports (current and retained)
+** \param report_timestamp - value of Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp
+**
+** \return pointer to NULL terminated dynamically allocated buffer containing the serialized report to send
+**
+**************************************************************************/
+char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp, char *report_format)
+{
+ char *result = NULL;
+
+ if (strcmp(report_format, BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE) == 0) {
+ result = bulkdata_generate_json_name_value_pair_report(bp, report_timestamp);
+ } else if (strcmp(report_format, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) == 0) {
+ result = create_json_obj_hier_report(bp, report_timestamp);
+ }
+
+ return result;
+}
+
+/*********************************************************************//**
+**
+** safe_asprintf
+**
+** Wrapper around asprintf that calls terminate in case of error
@ -739,18 +954,13 @@
+ return output;
+}
+
+/*********************************************************************//**
+**
** bulkdata_compress_report
/*********************************************************************//**
**
** Compresses the report to send
@@ -3020,9 +3496,18 @@ int bulkdata_schedule_sending_http_repor
** bulkdata_compress_report
@@ -3070,6 +3729,20 @@ int bulkdata_schedule_sending_http_report(profile_ctrl_params_t *ctrl, bulkdata_
flags |= BDC_FLAG_DATE_HEADER;
}
- if (strcmp(ctrl->report_format, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) == 0)
- {
- flags |= BDC_FLAG_HEADER_OBJ_HIER;
+ if (strcmp(ctrl->encoding_type, BULKDATA_ENCODING_TYPE_JSON) == 0) {
+ if (strcmp(ctrl->report_format, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) == 0) {
+ flags |= BDC_FLAG_HEADER_OBJ_HIER;
@ -763,6 +973,8 @@
+ } else {
+ flags |= BDC_FLAG_HEADER_PER_ROW;
+ }
}
+ }
+
// Exit if failed to post a message to BDC thread
// NOTE: Ownership of full_url, query_string, report, username and password passes to BDC_EXEC
err = BDC_EXEC_PostReportToSend(bp->profile_id, full_url, query_string, username, password, report, report_len, flags);

View file

@ -1,20 +0,0 @@
--- a/src/core/data_model.c
+++ b/src/core/data_model.c
@@ -160,6 +160,7 @@ int SetVendorParam(dm_node_t *node, char
double_link_t *FindLinkToFirstObject(double_linked_list_t *list);
int OverrideNodeType(dm_node_t *node, dm_node_type_t type, char *schema_path, dm_instances_t *inst);
+extern bool is_running_cli_local_command;
/*********************************************************************//**
**
** DATA_MODEL_Init
@@ -267,7 +268,9 @@ int DATA_MODEL_Init(void)
}
// Set the default values of OUI, Serial Number and (LocalAgent) EndpointID, and cache EndpointID
+ if (is_running_cli_local_command == false) {
err = DEVICE_LOCAL_AGENT_SetDefaults();
+ }
if (err != USP_ERR_OK)
{
return err;

View file

@ -1,366 +0,0 @@
--- a/src/core/bdc_exec.c
+++ b/src/core/bdc_exec.c
@@ -549,9 +549,14 @@ int StartSendingReport(bdc_connection_t
// Set the list of headers
bc->headers = NULL;
bc->headers = curl_slist_append(bc->headers, "Content-Type: application/json; charset=UTF-8");
- bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: NameValuePair");
+ if (bc->flags & BDC_FLAG_HEADER_OBJ_HIER)
+ bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: ObjectHierarchy");
+ else
+ bc->headers = curl_slist_append(bc->headers, "BBF-Report-Format: NameValuePair");
+
if (bc->flags & BDC_FLAG_GZIP)
{
+ curl_easy_setopt(curl_ctx, CURLOPT_ACCEPT_ENCODING, "gzip");
bc->headers = curl_slist_append(bc->headers, "Content-Encoding: gzip");
}
--- a/src/core/bdc_exec.h
+++ b/src/core/bdc_exec.h
@@ -53,6 +53,6 @@ void BDC_EXEC_ScheduleExit(void);
#define BDC_FLAG_PUT 0x00000001 // If set, HTTP PUT should be used instead of HTTP POST when sending the report to the BDC server
#define BDC_FLAG_GZIP 0x00000002 // If set, the reports contants are Gzipped
#define BDC_FLAG_DATE_HEADER 0x00000004 // If set, the date header should be included in the HTTP post.
-
+#define BDC_FLAG_HEADER_OBJ_HIER 0x00000008 // If set, report format in header would be ObjectHierarchy otherwise NameValuePair
#endif
--- a/src/core/device_bulkdata.c
+++ b/src/core/device_bulkdata.c
@@ -71,7 +71,8 @@
//------------------------------------------------------------------------------
// Definitions for formats that we support
#define BULKDATA_ENCODING_TYPE "JSON"
-#define BULKDATA_JSON_REPORT_FORMAT "NameValuePair"
+#define BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE "NameValuePair"
+#define BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER "ObjectHierarchy"
// Definitions for Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp
@@ -162,6 +163,7 @@ typedef struct
char compression[9];
char method[9];
bool use_date_header;
+ char report_format[20];
} profile_ctrl_params_t;
//------------------------------------------------------------------------------
@@ -236,7 +238,7 @@ bulkdata_profile_t *bulkdata_find_free_p
bulkdata_profile_t *bulkdata_find_profile(int profile_id);
int bulkdata_calc_report_map(bulkdata_profile_t *bp, kv_vector_t *report_map);
int bulkdata_reduce_to_alt_name(char *spec, char *path, char *alt_name, char *out_buf, int buf_len);
-char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp);
+char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp, char *report_format);
unsigned char *bulkdata_compress_report(profile_ctrl_params_t *ctrl, char *input_buf, int input_len, int *p_output_len);
int bulkdata_schedule_sending_http_report(profile_ctrl_params_t *ctrl, bulkdata_profile_t *bp, unsigned char *json_report, int report_len);
int bulkdata_start_profile(bulkdata_profile_t *bp);
@@ -310,7 +312,7 @@ int DEVICE_BULKDATA_Init(void)
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.Parameter.{i}.Reference", "", Validate_BulkDataReference, NULL, DM_STRING);
// Device.BulkData.Profile.{i}.JSONEncoding
- err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportFormat", BULKDATA_JSON_REPORT_FORMAT, Validate_BulkDataReportFormat, NULL, DM_STRING);
+ err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportFormat", BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE, Validate_BulkDataReportFormat, NULL, DM_STRING);
err |= USP_REGISTER_DBParam_ReadWrite("Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp", BULKDATA_JSON_TIMESTAMP_FORMAT_EPOCH, Validate_BulkDataReportTimestamp, NULL, DM_STRING);
// Device.BulkData.Profile.{i}.HTTP
@@ -698,9 +700,11 @@ int Validate_BulkDataReference(dm_req_t
int Validate_BulkDataReportFormat(dm_req_t *req, char *value)
{
// Exit if trying to set a value outside of the range we accept
- if (strcmp(value, BULKDATA_JSON_REPORT_FORMAT) != 0)
+ if (strcmp(value, BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE) != 0 &&
+ strcmp(value, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) != 0)
{
- USP_ERR_SetMessage("%s: Only JSON Report Format supported is '%s'", __FUNCTION__, BULKDATA_JSON_REPORT_FORMAT);
+ USP_ERR_SetMessage("%s: Only JSON Report Format supported are '%s', '%s'", __FUNCTION__,
+ BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER);
return USP_ERR_INVALID_VALUE;
}
@@ -2008,6 +2012,14 @@ int bulkdata_platform_get_profile_contro
return err;
}
+ // Exit if unable to get ReportFormat
+ USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.JSONEncoding.ReportFormat", bp->profile_id);
+ err = DATA_MODEL_GetParameterValue(path, ctrl_params->report_format, sizeof(ctrl_params->report_format), 0);
+ if (err != USP_ERR_OK)
+ {
+ return err;
+ }
+
return USP_ERR_OK;
}
@@ -2283,7 +2295,7 @@ void bulkdata_process_profile_http(bulkd
}
// Exit if unable to generate the report
- json_report = bulkdata_generate_json_report(bp, ctrl.report_timestamp);
+ json_report = bulkdata_generate_json_report(bp, ctrl.report_timestamp, ctrl.report_format);
if (json_report == NULL)
{
USP_ERR_SetMessage("%s: bulkdata_generate_json_report failed", __FUNCTION__);
@@ -2333,7 +2345,8 @@ void bulkdata_process_profile_usp_event(
kv_pair_t kv;
report_t *cur_report;
char *json_report;
- char report_timestamp[33];
+ char report_timestamp[33] = {0};
+ char report_format[20] = {0};
// Exit if the MTP has not been connected to successfully after bootup
// This is to prevent BDC events being enqueued before the Boot! event is sent (the Boot! event is only sent after successfully connecting to the MTP).
@@ -2350,6 +2363,14 @@ void bulkdata_process_profile_usp_event(
return;
}
+ // Exit if unable to get ReportFormat
+ USP_SNPRINTF(path, sizeof(path), "Device.BulkData.Profile.%d.JSONEncoding.ReportFormat", bp->profile_id);
+ err = DATA_MODEL_GetParameterValue(path, report_format, sizeof(report_format), 0);
+ if (err != USP_ERR_OK)
+ {
+ return;
+ }
+
// When sending via USP events, only one report is ever sent in each USP event
// So ensure all retained reports are removed. NOTE: Clearing the reports here is only necessary when switching protocol from HTTP to USP event, and where HTTP had some unsent reports
bulkdata_clear_retained_reports(bp);
@@ -2367,7 +2388,7 @@ void bulkdata_process_profile_usp_event(
bp->num_retained_reports = 1;
// Exit if unable to generate the report
- json_report = bulkdata_generate_json_report(bp, report_timestamp);
+ json_report = bulkdata_generate_json_report(bp, report_timestamp, report_format);
if (json_report == NULL)
{
USP_ERR_SetMessage("%s: bulkdata_generate_json_report failed", __FUNCTION__);
@@ -2579,21 +2600,7 @@ int bulkdata_reduce_to_alt_name(char *sp
return USP_ERR_OK;
}
-/*********************************************************************//**
-**
-** bulkdata_generate_json_report
-**
-** Generates a JSON name-value pair format report
-** NOTE: The report contains all retained failed reports, as well as the current report
-** See TR-157 section A.4.2 (end) for an example, and section A.3.5.2 for layout of content containing failed report transmissions
-**
-** \param bp - pointer to bulk data profile containing all reports (current and retained)
-** \param report_timestamp - value of Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp
-**
-** \return pointer to NULL terminated dynamically allocated buffer containing the serialized report to send
-**
-**************************************************************************/
-char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp)
+static char *create_json_name_value_pair_report(bulkdata_profile_t *bp, char *report_timestamp)
{
JsonNode *top; // top of report
JsonNode *array; // array of reports (retained + current)
@@ -2608,7 +2615,6 @@ char *bulkdata_generate_json_report(bulk
long long value_as_ll;
unsigned long long value_as_ull;
bool value_as_bool;
- char *result;
int i, j;
char buf[32];
kv_pair_t *kv;
@@ -2631,7 +2637,7 @@ char *bulkdata_generate_json_report(bulk
}
else if (strcmp(report_timestamp, "ISO-8601")==0)
{
- result = iso8601_from_unix_time(report->collection_time, buf, sizeof(buf));
+ char *result = iso8601_from_unix_time(report->collection_time, buf, sizeof(buf));
if (result != NULL)
{
json_append_member(element, "CollectionTime", json_mkstring(buf));
@@ -2690,11 +2696,174 @@ char *bulkdata_generate_json_report(bulk
json_append_member(top, "Report", array);
// Serialize the JSON tree
- result = json_stringify(top, " ");
+ char *output = json_stringify(top, " ");
// Clean up the JSON tree
json_delete(top); // Other JsonNodes which are children of this top level tree will be deleted
+ return output;
+}
+
+static char *create_json_obj_hier_report(bulkdata_profile_t *bp, char *report_timestamp)
+{
+ JsonNode *top; // top of report
+ JsonNode *array; // array of reports (retained + current)
+ JsonNode *element; // element of json array, containing an individual report
+ JsonNode *temp;
+ char *param_path;
+ char *param_type_value;
+ char param_type;
+ char *param_value;
+ kv_vector_t *report_map;
+ report_t *report;
+ double value_as_number;
+ long long value_as_ll;
+ unsigned long long value_as_ull;
+ bool value_as_bool;
+ int i, j;
+ char buf[32];
+ kv_pair_t *kv;
+ int err;
+
+ top = json_mkobject();
+ array = json_mkarray();
+
+ // Iterate over all reports adding them to the JSON array
+ for (i=0; i < bp->num_retained_reports; i++)
+ {
+ report = &bp->reports[i];
+ report_map = &report->report_map;
+
+ // Add Collection time to each json report element (only if specified and not 'None')
+ element = json_mkobject();
+ if (strcmp(report_timestamp, "Unix-Epoch")==0)
+ {
+ json_append_member(element, "CollectionTime", json_mknumber(report->collection_time));
+ }
+ else if (strcmp(report_timestamp, "ISO-8601")==0)
+ {
+ char *result = iso8601_from_unix_time(report->collection_time, buf, sizeof(buf));
+ if (result != NULL)
+ {
+ json_append_member(element, "CollectionTime", json_mkstring(buf));
+ }
+ }
+
+ temp = element;
+ // Iterate over each parameter, adding it to the json element. Take account of the parameter's type
+ for (j=0; j < report_map->num_entries; j++)
+ {
+ char buff[2056] = {0};
+ char *pch = NULL, *pchr = NULL, *argv[128] = {0};
+ int n = 0;
+
+ kv = &report_map->vector[j];
+ param_path = kv->key;
+ param_type_value = kv->value;
+ param_type = param_type_value[0]; // First character denotes the type of the parameter
+ param_value = &param_type_value[1]; // Subsequent characters contain the parameter's value
+
+ strncpy(buff, param_path, sizeof(buff));
+ for (pch = strtok_r(buff, ".", &pchr); pch != NULL; pch = strtok_r(NULL, ".", &pchr)) {
+ int idx;
+ JsonNode *obj = element;
+ argv[n] = pch;
+
+ for (idx = 0; idx <= n; idx++) {
+ if (obj == NULL)
+ break;
+ obj = json_find_member(obj, argv[idx]);
+ }
+
+ if (obj)
+ temp = obj;
+ else {
+ if (pchr != NULL && *pchr != '\0') {
+ // It is a DMOBJ
+ JsonNode *new = json_mkobject();
+ json_append_member(temp, pch, new);
+ temp = new;
+ } else {
+ // It is a DMPARAM
+ switch (param_type)
+ {
+ case 'S':
+ json_append_member(temp, pch, json_mkstring(param_value) );
+ break;
+
+ case 'U':
+ value_as_ull = strtoull(param_value, NULL, 10);
+ json_append_member(temp, pch, json_mkulonglong(value_as_ull) );
+ break;
+
+ case 'L':
+ value_as_ll = strtoll(param_value, NULL, 10);
+ json_append_member(temp, pch, json_mklonglong(value_as_ll) );
+ break;
+
+ case 'N':
+ value_as_number = atof(param_value);
+ json_append_member(temp, pch, json_mknumber(value_as_number) );
+ break;
+
+ case 'B':
+ err = TEXT_UTILS_StringToBool(param_value, &value_as_bool);
+ if (err == USP_ERR_OK)
+ {
+ json_append_member(temp, pch, json_mkbool(value_as_bool) );
+ }
+ break;
+
+ default:
+ USP_ERR_SetMessage("%s: Invalid JSON parameter type ('%c') in report map for %s", __FUNCTION__, param_type_value[0], param_path);
+ break;
+ }
+ }
+ }
+ n++;
+ }
+ }
+
+ // Add the json element to the json array
+ json_append_element(array, element);
+ }
+
+ // Finally add the array to the report top level
+ json_append_member(top, "Report", array);
+
+ // Serialize the JSON tree
+ char *output = json_stringify(top, " ");
+
+ // Clean up the JSON tree
+ json_delete(top); // Other JsonNodes which are children of this top level tree will be deleted
+
+ return output;
+}
+
+/*********************************************************************//**
+**
+** bulkdata_generate_json_report
+**
+** Generates a JSON name-value pair or object-hierarchy format report
+** NOTE: The report contains all retained failed reports, as well as the current report
+** See TR-157 section A.4.2 (end) for an example, and section A.3.5.2 for layout of content containing failed report transmissions
+**
+** \param bp - pointer to bulk data profile containing all reports (current and retained)
+** \param report_timestamp - value of Device.BulkData.Profile.{i}.JSONEncoding.ReportTimestamp
+**
+** \return pointer to NULL terminated dynamically allocated buffer containing the serialized report to send
+**
+**************************************************************************/
+char *bulkdata_generate_json_report(bulkdata_profile_t *bp, char *report_timestamp, char *report_format)
+{
+ char *result = NULL;
+
+ if (strcmp(report_format, BULKDATA_JSON_REPORT_FORMAT_NAME_VALUE) == 0) {
+ result = create_json_name_value_pair_report(bp, report_timestamp);
+ } else if (strcmp(report_format, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) == 0) {
+ result = create_json_obj_hier_report(bp, report_timestamp);
+ }
+
return result;
}
@@ -2851,6 +3020,11 @@ int bulkdata_schedule_sending_http_repor
flags |= BDC_FLAG_DATE_HEADER;
}
+ if (strcmp(ctrl->report_format, BULKDATA_JSON_REPORT_FORMAT_OBJ_HIER) == 0)
+ {
+ flags |= BDC_FLAG_HEADER_OBJ_HIER;
+ }
+
// Exit if failed to post a message to BDC thread
// NOTE: Ownership of full_url, query_string, report, username and password passes to BDC_EXEC
err = BDC_EXEC_PostReportToSend(bp->profile_id, full_url, query_string, username, password, report, report_len, flags);

View file

@ -1,37 +0,0 @@
--- a/src/core/cli_server.c
+++ b/src/core/cli_server.c
@@ -753,6 +753,15 @@ int ExecuteCli_Get(char *arg1, char *arg
}
#endif
+ char *path[2] = {0};
+
+ path[0] = arg1;
+ if (arg1 == NULL) {
+ vendor_create_dm_cache(path, 0);
+ } else {
+ vendor_create_dm_cache(path, 1);
+ }
+
// Exit if unable to get a list of all parameters referenced by the expression
STR_VECTOR_Init(&params);
INT_VECTOR_Init(&group_ids);
--- a/src/core/data_model.h
+++ b/src/core/data_model.h
@@ -371,5 +371,6 @@ bool DM_PRIV_IsChildOf(char *path, dm_no
bool DM_PRIV_IsChildNodeOf(dm_node_t *node, dm_node_t *parent_node);
bool DM_PRIV_AreAllChildrenGroupId(dm_node_t *parent, int group_id);
+int vendor_create_dm_cache(char *paths[], int num_paths);
#endif
--- a/src/core/handle_get.c
+++ b/src/core/handle_get.c
@@ -123,6 +123,7 @@ void MSG_HANDLER_HandleGet(Usp__Msg *usp
goto exit;
}
+ vendor_create_dm_cache(path_exprs, num_path_expr);
// Calculate the number of hierarchical levels to traverse in the data model when performing partial path resolution
// NOTE: protocol buffer has depth as an unsigned quantity, but internally we use a signed number, so limit range to that of a signed number
depth = usp->body->request->get->max_depth;

View file

@ -1,5 +1,22 @@
--- a/src/core/data_model.c
+++ b/src/core/data_model.c
Index: obuspa-9.0.4.1/src/core/cli_server.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/cli_server.c
+++ obuspa-9.0.4.1/src/core/cli_server.c
@@ -715,10 +715,6 @@ int ExecuteCli_Get(str_vector_t *args)
USP_ASSERT(gge->value != NULL);
SendCliResponse("%s => %s\n", gge->path, gge->value);
}
- else
- {
- SendCliResponse("ERROR: %d retrieving %s (%s)\n", gge->err_code, gge->path, gge->err_msg);
- }
}
GROUP_GET_VECTOR_Destroy(&ggv);
Index: obuspa-9.0.4.1/src/core/data_model.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/data_model.c
+++ obuspa-9.0.4.1/src/core/data_model.c
@@ -1316,7 +1316,7 @@ int DATA_MODEL_NotifyInstanceAdded(char
// Exit if instance already exists - nothing to do
if (exists)

View file

@ -0,0 +1,62 @@
Index: obuspa-9.0.4.1/src/core/cli_server.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/cli_server.c
+++ obuspa-9.0.4.1/src/core/cli_server.c
@@ -501,6 +501,7 @@ int CLI_SERVER_ExecuteCliCommand(char *c
SendCliResponse("WARNING: Discarding unused args: %s\n", args.vector[cli_cmd->max_args+1]);
}
+ vendor_create_dm_cache(NULL, 0);
// Process command
err = cli_cmd->exec_cmd(&args);
print_help = false;
@@ -683,6 +684,13 @@ int ExecuteCli_Get(str_vector_t *args)
}
#endif
+ if (arg1 != NULL) {
+ char *path[2] = {0};
+
+ path[0] = arg1;
+ vendor_create_dm_cache(path, 1);
+ }
+
// Exit if unable to get a list of all parameters referenced by the expression
STR_VECTOR_Init(&params);
INT_VECTOR_Init(&group_ids);
Index: obuspa-9.0.4.1/src/core/data_model.h
===================================================================
--- obuspa-9.0.4.1.orig/src/core/data_model.h
+++ obuspa-9.0.4.1/src/core/data_model.h
@@ -370,5 +370,6 @@ int DM_PRIV_ReRegister_DBParam_Default(c
bool DM_PRIV_IsChildNodeOf(dm_node_t *node, dm_node_t *parent_node);
void DM_PRIV_GetAllEventsAndCommands(dm_node_t *node, str_vector_t *events, str_vector_t *commands);
+int vendor_create_dm_cache(char *paths[], int num_paths);
#endif
Index: obuspa-9.0.4.1/src/core/handle_get.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/handle_get.c
+++ obuspa-9.0.4.1/src/core/handle_get.c
@@ -123,6 +123,7 @@ void MSG_HANDLER_HandleGet(Usp__Msg *usp
goto exit;
}
+ vendor_create_dm_cache(path_exprs, num_path_expr);
// Calculate the number of hierarchical levels to traverse in the data model when performing partial path resolution
// NOTE: protocol buffer has depth as an unsigned quantity, but internally we use a signed number, so limit range to that of a signed number
depth = usp->body->request->get->max_depth;
Index: obuspa-9.0.4.1/src/core/msg_handler.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/msg_handler.c
+++ obuspa-9.0.4.1/src/core/msg_handler.c
@@ -862,6 +862,8 @@ int HandleUspMessage(Usp__Msg *usp, char
MSG_HANDLER_UspMsgTypeToString(usp->header->msg_type),
iso8601_cur_time(buf, sizeof(buf)) );
+ // Drop the cached data before processing next message
+ vendor_create_dm_cache(NULL, 0);
// Process the message
cur_msg_type = usp_msg_type;
switch(usp_msg_type)

View file

@ -1,5 +1,7 @@
--- a/src/core/device.h
+++ b/src/core/device.h
Index: obuspa-9.0.4.1/src/core/device.h
===================================================================
--- obuspa-9.0.4.1.orig/src/core/device.h
+++ obuspa-9.0.4.1/src/core/device.h
@@ -338,6 +338,10 @@ void DEVICE_CONTROLLER_SetInheritedRole(
int DEVICE_CONTROLLER_CountEnabledWebsockClientConnections(void);
#endif
@ -11,8 +13,10 @@
#ifndef REMOVE_USP_BROKER
int DEVICE_SUBSCRIPTION_RouteNotification(Usp__Msg *usp, int instance);
bool DEVICE_SUBSCRIPTION_MarkVendorLayerSubs(int broker_instance, subs_notify_t notify_type, char *path, int group_id);
--- a/src/core/device_controller.c
+++ b/src/core/device_controller.c
Index: obuspa-9.0.4.1/src/core/device_controller.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/device_controller.c
+++ obuspa-9.0.4.1/src/core/device_controller.c
@@ -967,6 +967,78 @@ int DEVICE_CONTROLLER_QueueBinaryMessage
return USP_ERR_OK;
}
@ -92,9 +96,11 @@
/*********************************************************************//**
**
** DEVICE_CONTROLLER_IsMTPConfigured
--- a/src/core/msg_handler.c
+++ b/src/core/msg_handler.c
@@ -1210,6 +1210,15 @@ int ValidateUspRecord(UspRecord__Record
Index: obuspa-9.0.4.1/src/core/msg_handler.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/msg_handler.c
+++ obuspa-9.0.4.1/src/core/msg_handler.c
@@ -1219,6 +1219,15 @@ int ValidateUspRecord(UspRecord__Record
usp_service_instance = USP_BROKER_GetUspServiceInstance(rec->from_id, 0);
#endif

View file

@ -1,6 +1,8 @@
--- a/src/core/mqtt.c
+++ b/src/core/mqtt.c
@@ -256,6 +256,8 @@ void MqttSubscriptionDestroy(mqtt_subscr
Index: obuspa-9.0.4.1/src/core/mqtt.c
===================================================================
--- obuspa-9.0.4.1.orig/src/core/mqtt.c
+++ obuspa-9.0.4.1/src/core/mqtt.c
@@ -258,6 +258,8 @@ void MqttSubscriptionDestroy(mqtt_subscr
#define DEFINE_MQTT_TrustCertVerifyCallbackIndex(index) \
int MQTT_TrustCertVerifyCallback_##index (int preverify_ok, X509_STORE_CTX *x509_ctx) \
{\
@ -9,7 +11,7 @@
return DEVICE_SECURITY_TrustCertVerifyCallbackWithCertChain(preverify_ok, x509_ctx, &mqtt_clients[index].cert_chain);\
}
@@ -266,6 +268,11 @@ DEFINE_MQTT_TrustCertVerifyCallbackIndex
@@ -268,6 +270,11 @@ DEFINE_MQTT_TrustCertVerifyCallbackIndex
DEFINE_MQTT_TrustCertVerifyCallbackIndex(2);
DEFINE_MQTT_TrustCertVerifyCallbackIndex(3);
DEFINE_MQTT_TrustCertVerifyCallbackIndex(4);
@ -21,7 +23,7 @@
// Add more, with incrementing indexes here, if you change MAX_MQTT_CLIENTS
//------------------------------------------------------------------------------------
@@ -276,10 +283,15 @@ ssl_verify_callback_t* mqtt_verify_callb
@@ -278,10 +285,15 @@ ssl_verify_callback_t* mqtt_verify_callb
MQTT_TrustCertVerifyCallbackIndex(2),
MQTT_TrustCertVerifyCallbackIndex(3),
MQTT_TrustCertVerifyCallbackIndex(4),