cccs: add ConnectCore Cloud Services maintenance state example

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

Signed-off-by: Tatiana Leon <Tatiana.Leon@digi.com>
This commit is contained in:
Tatiana Leon 2023-12-18 14:58:48 +01:00
parent 1ca37f3016
commit c7241a9076
5 changed files with 361 additions and 0 deletions

View File

@ -16,6 +16,7 @@
SUBDIRS := \
cccs-data-request-example \
cccs-maintenance-status-example \
cccs-upload-binary-file-example \
cccs-upload-data-points-example

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-maintenance-status-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,79 @@
Digi ConnectCore Cloud Services Maintenance Status Example Application
======================================================================
Example application to set the device maintenance status using ConnectCore Cloud
Services.
This application alternates 'In maintenance' and 'In service' status keeping
them the provided number of seconds as parameters.
If no parameters are provided each status is configured for 60 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-maintenance-status-example
cccs-maintenance-status-example[1216]: [INFO] MNT: Setting maintenance to 'true'
Device IN MAINTENANCE for 60 seconds
Digi Remote Manager CAN:
* Apply compatible configurations
* Execute existing automations
cccs-maintenance-status-example[1216]: [INFO] MNT: Setting maintenance to 'false'
Device IN SERVICE for 60 seconds
Digi Remote Manager CANNOT:
* Apply configurations (unless 'allow' is set)
* Execute automations (unless 'allow' is set)
cccs-maintenance-status-example[1216]: [INFO] MNT: Setting maintenance to 'true'
Device IN MAINTENANCE for 60 seconds
Digi Remote Manager CAN:
* Apply compatible configurations
* Execute existing automations
cccs-maintenance-status-example[1216]: [INFO] MNT: Setting maintenance to 'false'
Device IN SERVICE for 60 seconds
Digi Remote Manager CANNOT:
* Apply configurations (unless 'allow' is set)
* Execute automations (unless 'allow' is set)
[...]
```
Check the status of your device from Digi Remote Manager:
1. Go to https://remotemanager.digi.com/.
2. Login with your credentials.
3. Click on the **Device ID** of your device in the **Devices** page.
4. Check the **Service Status** on the **Details** tab.
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,221 @@
/*
* 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 <errno.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MNT_INTERVAL 60 /* seconds */
#define LOOP_MS 100
static bool stop_requested = false;
/*
* usage_and_exit() - Show usage information and exit with 'val' return value
*
* @name: Application name.
* @val: The exit code.
*/
static void usage_and_exit(char *name, int val)
{
fprintf(stdout,
"Example application to alternate 'in maintenance' and 'in service' status\n"
"\n"
"Usage: %s\n"
"The application sets the device:\n"
" In maintenance for %d seconds.\n"
" In service for %d seconds.\n"
"\n"
"Usage: %s <in-maintenance-seconds> <in-service-seconds>\n"
" In maintenance for <in-maintenance-seconds> seconds.\n"
" In service for <in-service-seconds> seconds.\n"
"\n", name, MNT_INTERVAL, MNT_INTERVAL, name);
exit(val);
}
/*
* 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 = true;
exit(0);
}
/*
* cleanup() - Frees all the allocated memory before exiting
*/
static void cleanup(void)
{
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);
}
/*
* wait_loop() - Loop to wait the provided number of seconds
*
* @timeout: Number of seconds to wait.
*/
static void wait_loop(long timeout)
{
long n_loops, loop;
n_loops = timeout * 1000 / LOOP_MS;
for (loop = 0; loop < n_loops; loop++) {
struct timespec sleepValue = {0};
if (stop_requested)
break;
sleepValue.tv_nsec = LOOP_MS * 1000 * 1000;
nanosleep(&sleepValue, NULL);
}
}
int main(int argc, char *argv[])
{
char *name = basename(argv[0]);
bool status = false;
long mnt_sec = MNT_INTERVAL, srv_sec = MNT_INTERVAL;
init_logger(LOG_INFO, LOG_CONS | LOG_NDELAY | LOG_PID | LOG_PERROR, name);
if (argc != 1 && argc != 3)
usage_and_exit(name, EXIT_FAILURE);
if (argc == 3) {
char *endptr = NULL;
mnt_sec = strtol(argv[1], &endptr, 10);
//log_info("mnt_sec=%ld, strlen(endptr)=%lu", mnt_sec, strlen(endptr));
if (errno != 0 || mnt_sec < 0 || strlen(endptr))
goto invalid_values;
srv_sec = strtol(argv[2], &endptr, 10);
//log_info("srv_sec=%ld", srv_sec);
if (errno != 0 || srv_sec < 0 || strlen(endptr))
goto invalid_values;
if (mnt_sec == 0 && srv_sec == 0)
goto invalid_values;
}
register_signals();
if (!cccs_is_daemon_ready(CCCSD_NO_WAIT)) {
log_error("%s: CCCS daemon not ready... exiting", __func__);
return EXIT_FAILURE;
}
while (!stop_requested) {
cccs_comm_error_t ret;
cccs_resp_t resp;
bool success = false;
long timeout;
status = !status;
timeout = status ? mnt_sec : srv_sec;
if (timeout == 0)
continue;
ret = cccs_set_maintenance_status(status, 3, &resp);
if (ret != CCCS_SEND_ERROR_NONE) {
log_error("%s: Unable to set maintenance status", __func__);
} else if (resp.code != 0) {
if (resp.hint)
log_error("%s: Unable to set maintenance status: %s (%d)",
__func__, resp.hint, resp.code);
else
log_error("%s: Unable to set maintenance status: %d",
__func__, resp.code);
} else {
success = true;
}
free(resp.hint);
if (success) {
if (status) {
if (mnt_sec == 0 || srv_sec == 0)
printf("Device IN MAINTENANCE\n");
else
printf("Device IN MAINTENANCE for %ld seconds\n", timeout);
printf("Digi Remote Manager CAN:\n");
printf(" * Apply compatible configurations\n");
printf(" * Execute existing automations\n");
} else {
if (mnt_sec == 0 || srv_sec == 0)
printf("Device IN SERVICE\n");
else
printf("Device IN SERVICE for %ld seconds\n", timeout);
printf("Digi Remote Manager CANNOT:\n");
printf(" * Apply configurations (unless 'allow' is set)\n");
printf(" * Execute automations (unless 'allow' is set)\n");
}
if (mnt_sec == 0 || srv_sec == 0)
break;
} else {
/* Retry the same status */
status = !status;
}
wait_loop(timeout);
}
return EXIT_SUCCESS;
invalid_values:
printf("Invalid time values\n");
usage_and_exit(name, EXIT_FAILURE);
}

View File

@ -293,4 +293,24 @@ to stream `binary_dp`.
<platform>ccmp13-dvk</platform>
</platforms>
</sample>
<sample id="cccs-maintenance-status-example">
<name>Digi CCCS set maintenance Example</name>
<description>
Example application to enable/disable maintenance status.
</description>
<path>cccs-maintenance-status-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>ccimx93-dvk</platform>
<platform>ccmp15-dvk</platform>
<platform>ccmp13-dvk</platform>
</platforms>
</sample>
</samples>