diff --git a/cccs-data-request-example/Makefile b/cccs-data-request-example/Makefile new file mode 100644 index 0000000..37c74e9 --- /dev/null +++ b/cccs-data-request-example/Makefile @@ -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) diff --git a/cccs-data-request-example/README.md b/cccs-data-request-example/README.md new file mode 100644 index 0000000..10e12da --- /dev/null +++ b/cccs-data-request-example/README.md @@ -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 + + + + + + + + + + + ``` + 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 + + + + + Time: Fri Sep 1 11:36:33 2023 + + + + + ``` +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: + +``` +~$ . /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. diff --git a/cccs-data-request-example/main.c b/cccs-data-request-example/main.c new file mode 100644 index 0000000..7c0529f --- /dev/null +++ b/cccs-data-request-example/main.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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): + * + * + * + * + * + * + * + * + * + * + * + * + */ + +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; +} diff --git a/cccs-examples.mk b/cccs-examples.mk new file mode 100644 index 0000000..f5930eb --- /dev/null +++ b/cccs-examples.mk @@ -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 diff --git a/cccs-upload-data-points-example/Makefile b/cccs-upload-data-points-example/Makefile new file mode 100644 index 0000000..3d9d137 --- /dev/null +++ b/cccs-upload-data-points-example/Makefile @@ -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) diff --git a/cccs-upload-data-points-example/README.md b/cccs-upload-data-points-example/README.md new file mode 100644 index 0000000..afe7e0b --- /dev/null +++ b/cccs-upload-data-points-example/README.md @@ -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: + +``` +~$ . /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. diff --git a/cccs-upload-data-points-example/main.c b/cccs-upload-data-points-example/main.c new file mode 100644 index 0000000..a3122f8 --- /dev/null +++ b/cccs-upload-data-points-example/main.c @@ -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 +#include +#include +#include +#include +#include + +#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; +} diff --git a/samples-manifest.xml b/samples-manifest.xml index 8135f23..ce97fb3 100644 --- a/samples-manifest.xml +++ b/samples-manifest.xml @@ -223,4 +223,51 @@ A key modifier may be used to further differentiate the key used in a particular ccimx8mm-dvk + + Digi CCCS data request Example + +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. + + cccs-data-request-example + + ccimx6sbc + ccimx6qpsbc + ccimx6ulstarter + ccimx6ulsbc + ccimx8x-sbc-express + ccimx8x-sbc-pro + ccimx8mn-dvk + ccimx8mm-dvk + ccmp15-dvk + ccmp13-dvk + ccimx93-dvk + + + + Digi CCCS upload data points Example + +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. + + cccs-upload-data-points-example + + ccimx6sbc + ccimx6qpsbc + ccimx6ulstarter + ccimx6ulsbc + ccimx8x-sbc-express + ccimx8x-sbc-pro + ccimx8mn-dvk + ccimx8mm-dvk + ccmp15-dvk + ccmp13-dvk + ccimx93-dvk + +