cccs: add ConnectCore Cloud Services examples

https://onedigi.atlassian.net/browse/DEL-8628

Signed-off-by: Tatiana Leon <Tatiana.Leon@digi.com>
This commit is contained in:
Tatiana Leon 2023-09-01 14:25:12 +02:00
parent 79aa8410c2
commit 82ee13f97e
8 changed files with 805 additions and 0 deletions

View File

@ -0,0 +1,40 @@
#
# Copyright 2023, Digi International Inc.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
BINARY := cccs-data-request-example
CFLAGS += -Wall
CFLAGS += $(shell pkg-config --cflags cccs)
LDLIBS += $(shell pkg-config --libs --static cccs)
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
$(BINARY): $(OBJS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
.PHONY: install
install: $(BINARY)
install -d $(DESTDIR)/usr/bin
install -m 0755 $^ $(DESTDIR)/usr/bin/
.PHONY: all
all: $(BINARY)
.PHONY: clean
clean:
-rm -f *.o $(BINARY)

View File

@ -0,0 +1,118 @@
Digi ConnectCore Cloud Services Data Request Example Application
================================================================
Example application to listen to data requests from Remote Manager using
ConnectCore Cloud Services.
This application registers a `get_time` data request.
When this request arrives the application sends back the current time.
Running the application
-----------------------
This application requires `cccsd` (ConnectCore Cloud Services daemon) running
on the device.
Once the binary is in the target, launch the application:
```
# ./cccs-data-request-example
cccs-data-request-example[1011]: [DEBUG] CCCSD: Connected to CCCSD (s=4)
cccs-data-request-example[1011]: [DEBUG] CCCS daemon ready
cccs-data-request-example[1011]: [INFO] DREQ: Registering 'get_time' data request
cccs-data-request-example[1011]: [DEBUG] CCCSD: Connected to CCCSD (s=7)
cccs-data-request-example[1011]: [DEBUG] CCCSD: Success from CCCSD
Waiting for Remote Manager request...
Press 'q' and 'Enter' to exit
```
Send a `get_time` data request to your device.
To do so:
1. Go to https://remotemanager.digi.com/.
2. Login with your credentials.
3. Get your device identifier from the **Devices** page:
a. Go to the **Management > Devices** tab.
b. If you have more than one device, you can filter using the **MAC**
address of your device:
1. Click on the filter text box and select **MAC**.
2. Type the MAC address of your device and press `Enter`.
3. Copy the **Device ID** of your device from the table by using the **Copy Device ID** button that appears next to it when you hover over the item.
4. Go to the **System > API Explorer** tab. From here you can test the Web
Services API.
5. Click the **Examples** combo.
6. Select **SCI > Data Service > Send Request**.
A request appears inside the Body text box.
7. Modify the request to stop the sampling process on your device:
a. Replace the `device id` value with the copied one.
b. Replace the `target_name` value with `get_time`.
c. Remove the payload of the request.
The request should be similar to the following:
```xml
<sci_request version="1.0">
<data_service>
<targets>
<device id="00000000-00000000-00XXXXXX-XXXXXXXX" />
</targets>
<requests>
<device_request target_name="get_time"></device_request>
</requests>
</data_service>
</sci_request>
```
Where `00000000-00000000-00XXXXXX-XXXXXXXX` is the Device ID.
8. Click **Send** to send the request to your device.
In the **Response** text box you can review the answer from the device:
```xml
<sci_reply version="1.0">
<data_service>
<device id="00000000-00000000-00XXXXXX-XXXXXXXX">
<requests>
<device_request target_name="get_time" status="0">Time: Fri Sep 1 11:36:33 2023</device_request>
</requests>
</device>
</data_service>
</sci_reply>
```
Where `00000000-00000000-00XXXXXX-XXXXXXXX` is the Device ID.
The application prints out the received request:
```
[...]
Waiting for Remote Manager request...
Press 'q' and 'Enter' to exit
cccs-data-request-example[1163]: [DEBUG] get_time_cb: target='get_time'
cccs-data-request-example[1163]: [DEBUG] get_time_status_cb: target='get_time' - error='0' - error-hint='Success'
```
Compiling the application
-------------------------
This example can be compiled using a Digi Embedded Yocto based toolchain. Make
sure to source the corresponding toolchain of the platform you are using,
for example, for ConnectCore 6UL:
```
~$ . <DEY-toolchain-path>/environment-setup-cortexa7t2hf-neon-dey-linux-gnueabi
~$ make
```
For more information, see the [Digi Embedded Yocto online documentation](https://github.com/digi-embedded/meta-digi).
License
-------
Copyright 2023, Digi International Inc.
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

View File

@ -0,0 +1,217 @@
/*
* Copyright 2023, Digi International Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <cccs_services.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#if !(defined UNUSED_ARGUMENT)
#define UNUSED_ARGUMENT(a) (void)(a)
#endif
#define TARGET_GET_TIME "get_time"
/*
* sigaction_handler() - Handler to execute after receiving a signal
*
* @signum: Received signal.
*/
static void sigaction_handler(int signum)
{
log_debug("%s: received signal %d", __func__, signum);
exit(0);
}
/*
* cleanup() - Frees all the allocated memory before exiting
*/
static void cleanup(void)
{
cccs_resp_t resp;
cccs_comm_error_t ret;
ret = cccs_remove_request_target(TARGET_GET_TIME, &resp);
if (ret != CCCS_SEND_ERROR_NONE) {
log_error("%s: Cannot unregister target '%s': CCCSD error %d",
__func__, TARGET_GET_TIME, ret);
} else if (resp.code != 0) {
if (resp.hint)
log_error("%s: Cannot unregister target '%s': CCCSD error, %s (%d)",
__func__, TARGET_GET_TIME, resp.hint, resp.code);
else
log_error("%s: Cannot unregister target '%s': CCCSD error, %d",
__func__, TARGET_GET_TIME, resp.code);
}
free(resp.hint);
deinit_logger();
}
/*
* register_signals() - Registers program signals
*/
static void register_signals(void)
{
struct sigaction new_action;
struct sigaction old_action;
atexit(cleanup);
new_action.sa_handler = sigaction_handler;
new_action.sa_flags = 0;
sigemptyset(&new_action.sa_mask);
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGINT, &new_action, NULL);
sigaction(SIGHUP, &old_action, NULL);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGHUP, &new_action, NULL);
sigaction(SIGTERM, &old_action, NULL);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGTERM, &new_action, NULL);
}
/*
* get_time_cb() - Data callback for 'get_time' data requests
*
* @target: Target ID of the data request (get_time).
* @req_buf_info: Buffer containing the data request.
* @resp_buf_info: Buffer to store the answer of the request.
*
* Logs information about the received request and executes the corresponding
* command.
*
* Return: 'CCCS_RECEIVE_ERROR_NONE' if success, any other value on failure.
*/
static cccs_receive_error_t get_time_cb(char const *const target,
cccs_buffer_info_t const *const req_buf_info,
cccs_buffer_info_t *const resp_buf_info)
{
time_t t = time(NULL);
char *time_str = ctime(&t);
UNUSED_ARGUMENT(req_buf_info);
log_debug("%s: target='%s'", __func__, target);
resp_buf_info->length = snprintf(NULL, 0, "Time: %s", time_str);
resp_buf_info->buffer = calloc(resp_buf_info->length + 1, sizeof(char));
if (resp_buf_info->buffer == NULL) {
log_error("%s: resp_buf_info calloc error", __func__);
return CCCS_RECEIVE_ERROR_INSUFFICIENT_MEMORY;
}
resp_buf_info->length = sprintf(resp_buf_info->buffer, "Time: %s", time_str);
return CCCS_RECEIVE_ERROR_NONE;
}
/*
* get_time_status_cb() - Status callback for 'get_time' data requests
*
* @target: Target ID of the data request (get_time)
* @resp_buf_info: Buffer containing the response data.
* @receive_error: The error status of the receive process.
* @receive_error_hint: The error hint from the connector service.
*
* This callback is executed when the response process has finished. It doesn't
* matter if everything worked or there was an error during the process.
*
* Cleans and frees the response buffer.
*/
static void get_time_status_cb(char const *const target,
cccs_buffer_info_t *const resp_buf_info,
int receive_error,
const char *const receive_error_hint)
{
log_debug("%s: target='%s' - error='%d' - error-hint='%s'",
__func__, target, receive_error, receive_error_hint);
/* Free the response buffer */
if (resp_buf_info != NULL)
free(resp_buf_info->buffer);
}
/*
* Use the following SCI request to test this example (insert your Device ID):
*
* <sci_request version="1.0">
* <data_service>
* <targets>
* <device id="00000000-00000000-XXXXXXXX-XXXXXXXX"/>
* </targets>
* <requests>
* <device_request target_name="get_time"/>
* </requests>
* </data_service>
* </sci_request>
*
*/
int main(int argc, char *argv[])
{
cccs_comm_error_t ret;
char *name = basename(argv[0]);
cccs_resp_t resp;
int read_char;
init_logger(LOG_DEBUG, LOG_CONS | LOG_NDELAY | LOG_PID | LOG_PERROR, name);
register_signals();
if (!cccs_is_daemon_ready(CCCSD_NO_WAIT)) {
log_error("%s: CCCS daemon not ready... exiting", __func__);
return EXIT_FAILURE;
}
ret = cccs_add_request_target(TARGET_GET_TIME, get_time_cb,
get_time_status_cb, &resp);
if (ret != CCCS_SEND_ERROR_NONE) {
log_error("%s: Cannot register target '%s': CCCSD error %d",
__func__, TARGET_GET_TIME, ret);
return EXIT_FAILURE;
} else if (resp.code != 0) {
if (resp.hint)
log_error("%s: Cannot register target '%s': CCCSD error, %s (%d)",
__func__, TARGET_GET_TIME, resp.hint, resp.code);
else
log_error("%s: Cannot register target '%s': CCCSD error, %d",
__func__, TARGET_GET_TIME, resp.code);
return EXIT_FAILURE;
}
free(resp.hint);
printf("Waiting for Remote Manager request...\n");
printf("Press 'q' and 'Enter' to exit\n");
do {
read_char = getchar();
} while (read_char != 'q');
return EXIT_SUCCESS;
}

28
cccs-examples.mk Normal file
View File

@ -0,0 +1,28 @@
#
# Copyright (c) 2023 Digi International Inc.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
SUBDIRS := \
cccs-data-request-example \
cccs-upload-data-points-example
all: $(SUBDIRS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
install clean:
for a in $(SUBDIRS); do $(MAKE) -C $$a $@; done

View File

@ -0,0 +1,40 @@
#
# Copyright 2023, Digi International Inc.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
BINARY := cccs-upload-data-points-example
CFLAGS += -Wall
CFLAGS += $(shell pkg-config --cflags cccs)
LDLIBS += $(shell pkg-config --libs --static cccs)
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
$(BINARY): $(OBJS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
.PHONY: install
install: $(BINARY)
install -d $(DESTDIR)/usr/bin
install -m 0755 $^ $(DESTDIR)/usr/bin/
.PHONY: all
all: $(BINARY)
.PHONY: clean
clean:
-rm -f *.o $(BINARY)

View File

@ -0,0 +1,68 @@
Digi ConnectCore Cloud Services Upload Data Points Example Application
======================================================================
Example application to upload data points to Remote Manager using ConnectCore
Cloud Services.
This application uploads an integer value with an incremented counter to a data
stream called 'incremental'. The counter value is incremented every 5 seconds.
The uploads takes place every 10 new samples, that is every 50 seconds.
Running the application
-----------------------
This application requires `cccsd` (ConnectCore Cloud Services daemon) running
on the device.
Once the binary is in the target, launch the application:
```
# ./cccs-upload-data-points-example
cccs-upload-data-points-example[1010]: [DEBUG] CCCSD: Connected to CCCSD (s=4)
cccs-upload-data-points-example[1010]: [DEBUG] CCCS daemon ready
cccs-upload-data-points-example[1090]: [INFO] Counter = 0
cccs-upload-data-points-example[1090]: [INFO] Counter = 1
cccs-upload-data-points-example[1090]: [INFO] Counter = 2
cccs-upload-data-points-example[1090]: [INFO] Counter = 3
cccs-upload-data-points-example[1090]: [INFO] Counter = 4
cccs-upload-data-points-example[1090]: [INFO] Counter = 5
cccs-upload-data-points-example[1090]: [INFO] Counter = 6
cccs-upload-data-points-example[1090]: [INFO] Counter = 7
cccs-upload-data-points-example[1090]: [INFO] Counter = 8
cccs-upload-data-points-example[1090]: [INFO] Counter = 9
cccs-upload-data-points-example[1090]: [INFO] Sending data sream with new incremental value
cccs-upload-data-points-example[1090]: [INFO] DP: Sending data points to CCCSD
cccs-upload-data-points-example[1090]: [DEBUG] CCCSD: Connected to CCCSD (s=4)
cccs-upload-data-points-example[1090]: [DEBUG] CCCSD: Success from CCCSD
cccs-upload-data-points-example[1090]: [INFO] Counter = 10
cccs-upload-data-points-example[1090]: [INFO] Counter = 11
```
Compiling the application
-------------------------
This example can be compiled using a Digi Embedded Yocto based toolchain. Make
sure to source the corresponding toolchain of the platform you are using,
for example, for ConnectCore 6UL:
```
~$ . <DEY-toolchain-path>/environment-setup-cortexa7t2hf-neon-dey-linux-gnueabi
~$ make
```
For more information, see the [Digi Embedded Yocto online documentation](https://github.com/digi-embedded/meta-digi).
License
-------
Copyright 2023, Digi International Inc.
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

View File

@ -0,0 +1,247 @@
/*
* Copyright 2023, Digi International Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <cccs_services.h>
#include <libgen.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#define STREAM_NAME "incremental"
#define DP_SLEEP_TIME 5
#define DP_NUMBER 10
static int stop_requested = 0;
static cccs_dp_collection_handle_t dp_collection;
/*
* destroy_data_stream() - Destroy the data collection with the included data streams
*
* @collection: Data point collection to destroy.
*
* Return: 'CCCS_DP_ERROR_NONE' if success, any other value on failure.
*/
static cccs_dp_error_t destroy_data_stream(cccs_dp_collection_handle_t collection)
{
log_debug("%s", "Destroying data collection");
return cccs_dp_destroy_collection(collection);
}
/*
* sigaction_handler() - Handler to execute after receiving a signal
*
* @signum: Received signal.
*/
static void sigaction_handler(int signum)
{
log_debug("%s: received signal %d", __func__, signum);
stop_requested = 1;
/* 'atexit' executes the cleanup function */
exit(0);
}
/*
* cleanup() - Frees all the allocated memory before exiting
*/
static void cleanup(void)
{
if (stop_requested)
destroy_data_stream(dp_collection);
deinit_logger();
}
/*
* register_signals() - Registers program signals
*/
static void register_signals(void)
{
struct sigaction new_action;
struct sigaction old_action;
atexit(cleanup);
new_action.sa_handler = sigaction_handler;
new_action.sa_flags = 0;
sigemptyset(&new_action.sa_mask);
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGINT, &new_action, NULL);
sigaction(SIGHUP, &old_action, NULL);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGHUP, &new_action, NULL);
sigaction(SIGTERM, &old_action, NULL);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGTERM, &new_action, NULL);
}
/*
* get_incremental_value() - Retrieves an incremental value each time
*
* Return: The new counter value.
*/
static int get_incremental_value(void)
{
static int counter = -1;
if (counter == INT_MAX)
counter = 0;
else
counter++;
log_info("Counter = %d", counter);
return counter;
}
/*
* init_data_stream() - Initialize a data point collection
*
* @collection: Data point collection to initialize
*
* This function creates a data point collection and adds the 'incremental'
* data stream to it.
*
* Return: 'CCCS_DP_ERROR_NONE' if success, any other value on failure.
*/
static cccs_dp_error_t init_data_stream(cccs_dp_collection_handle_t *collection)
{
cccs_dp_collection_handle_t c;
cccs_dp_error_t dp_error;
dp_error = cccs_dp_create_collection(&c);
if (dp_error != CCCS_DP_ERROR_NONE) {
log_error("%s: error %d", __func__, dp_error);
return dp_error;
}
*collection = c;
dp_error = cccs_dp_add_data_stream_to_collection_extra(c,
STREAM_NAME, CCCS_DP_KEY_DATA_INT32, true, "counts", NULL);
if (dp_error != CCCS_DP_ERROR_NONE) {
log_error("%s: error %d", __func__, dp_error);
cccs_dp_destroy_collection(c);
*collection = NULL;
}
return dp_error;
}
/*
* add_incremental_data_point() - Add a new incremental data point to the collection
*
* @collection: Data point collection to add the new data point.
*
* Return: 'CCCS_DP_ERROR_NONE' if success, any other value on failure.
*/
static cccs_dp_error_t add_incremental_data_point(cccs_dp_collection_handle_t collection)
{
cccs_dp_error_t dp_error;
dp_error = cccs_dp_add(collection, STREAM_NAME, get_incremental_value());
if (dp_error != CCCS_DP_ERROR_NONE)
log_error("%s: failed with error: %d", __func__, dp_error);
return dp_error;
}
/*
* send_data() - Send collected data to ConnectCore Cloud Services daemon
*
* @collection: Data point collection to with the data to send.
*
* Return: 0 if success, any other value on failure.
*/
static int send_data(cccs_dp_collection_handle_t collection)
{
cccs_comm_error_t ret;
cccs_resp_t resp;
log_info("%s", "Sending data sream with new incremental value");
ret = cccs_send_dp_collection_tout(collection, 5, &resp);
if (ret != CCCS_SEND_ERROR_NONE) {
log_error("%s: error sending data points: CCCSD error %d", __func__, ret);
} else if (resp.code != 0) {
if (resp.hint)
log_error("%s: error sending data points: CCCSD error %s (%d)", __func__, resp.hint, resp.code);
else
log_error("%s: error sending data points: CCCSD error %d", __func__, resp.code);
}
free(resp.hint);
return ret;
}
int main(int argc, char *argv[])
{
char *name = basename(argv[0]);
cccs_dp_error_t dp_error;
int i;
init_logger(LOG_DEBUG, LOG_CONS | LOG_NDELAY | LOG_PID | LOG_PERROR, name);
register_signals();
if (!cccs_is_daemon_ready(CCCSD_NO_WAIT)) {
log_error("%s: CCCS daemon not ready... exiting", __func__);
return EXIT_FAILURE;
}
dp_error = init_data_stream(&dp_collection);
if (dp_error != CCCS_DP_ERROR_NONE) {
log_error("%s: Cannot initialize data stream, error %d",
__func__, dp_error);
return EXIT_FAILURE;
}
stop_requested = 0;
while (!stop_requested) {
/* Collect DP_NUMBER data points sampled each DP_SLEEP_TIME seconds */
for (i = 0; i < DP_NUMBER; i++) {
dp_error = add_incremental_data_point(dp_collection);
if (dp_error != CCCS_DP_ERROR_NONE) {
log_error("%s: Cannot add data point, error %d",
__func__, dp_error);
i--;
}
if (i + 1 < DP_NUMBER)
sleep(DP_SLEEP_TIME);
}
/* Send the block of collected data points */
send_data(dp_collection);
if (i == DP_NUMBER)
sleep(DP_SLEEP_TIME);
}
return EXIT_SUCCESS;
}

View File

@ -223,4 +223,51 @@ A key modifier may be used to further differentiate the key used in a particular
<platform>ccimx8mm-dvk</platform>
</platforms>
</sample>
<sample id="cccs-data-request-example">
<name>Digi CCCS data request Example</name>
<description>
Example application to listen to data requests from Remote Manager using
ConnectCore Cloud Services.
This application registers a `get_time` data request.
When this request arrives the application sends back the current time.
</description>
<path>cccs-data-request-example</path>
<platforms>
<platform>ccimx6sbc</platform>
<platform>ccimx6qpsbc</platform>
<platform>ccimx6ulstarter</platform>
<platform>ccimx6ulsbc</platform>
<platform>ccimx8x-sbc-express</platform>
<platform>ccimx8x-sbc-pro</platform>
<platform>ccimx8mn-dvk</platform>
<platform>ccimx8mm-dvk</platform>
<platform>ccmp15-dvk</platform>
<platform>ccmp13-dvk</platform>
<platform>ccimx93-dvk</platform>
</platforms>
</sample>
<sample id="cccs-upload-data-points-example">
<name>Digi CCCS upload data points Example</name>
<description>
Example application to upload data points to Remote Manager using ConnectCore
Cloud Services.
This application uploads an integer value with an incremented counter to a data
stream called 'incremental'. The counter value is incremented every 5 seconds.
The uploads takes place every 10 new samples, that is every 50 seconds.
</description>
<path>cccs-upload-data-points-example</path>
<platforms>
<platform>ccimx6sbc</platform>
<platform>ccimx6qpsbc</platform>
<platform>ccimx6ulstarter</platform>
<platform>ccimx6ulsbc</platform>
<platform>ccimx8x-sbc-express</platform>
<platform>ccimx8x-sbc-pro</platform>
<platform>ccimx8mn-dvk</platform>
<platform>ccimx8mm-dvk</platform>
<platform>ccmp15-dvk</platform>
<platform>ccmp13-dvk</platform>
<platform>ccimx93-dvk</platform>
</platforms>
</sample>
</samples>