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:
parent
1ca37f3016
commit
c7241a9076
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
SUBDIRS := \
|
SUBDIRS := \
|
||||||
cccs-data-request-example \
|
cccs-data-request-example \
|
||||||
|
cccs-maintenance-status-example \
|
||||||
cccs-upload-binary-file-example \
|
cccs-upload-binary-file-example \
|
||||||
cccs-upload-data-points-example
|
cccs-upload-data-points-example
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -293,4 +293,24 @@ to stream `binary_dp`.
|
||||||
<platform>ccmp13-dvk</platform>
|
<platform>ccmp13-dvk</platform>
|
||||||
</platforms>
|
</platforms>
|
||||||
</sample>
|
</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>
|
</samples>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue