aws iot sample: add support to connect to AWS IoT and report CPU temperature
The application connects to AWS IoT and monitors the CPU temperature.
It uploads the Thing Shadow every minute (per param in config file) or when the
temperature variation is bigger than 1C (per param in the config file).
This commit adds the following configuration parameters:
* 'shadow_report_rate': Frequency at which the device reports its shadow to
the cloud (in seconds).
* 'temperature_variation': Minimum absolute value of the difference between
last reported temperature and the current value to report again.
https://jira.digi.com/browse/DEL-4149
Signed-off-by: Tatiana Leon <tatiana.leon@digi.com>
This commit is contained in:
parent
dc2599fd28
commit
1fff418887
|
|
@ -2,6 +2,74 @@ AWS IoT device SDK Demo Application
|
||||||
===================================
|
===================================
|
||||||
Demo application to connect devices to AWS IoT.
|
Demo application to connect devices to AWS IoT.
|
||||||
|
|
||||||
|
This application monitors the CPU temperature.
|
||||||
|
|
||||||
|
The demo uploads the device Thing Shadow every minute or when the difference
|
||||||
|
between the temperature current value and the last reported is bigger than a
|
||||||
|
configured value.
|
||||||
|
|
||||||
|
The repository has the following directories:
|
||||||
|
|
||||||
|
* cfg_files: demo configuration file
|
||||||
|
* src: application source code
|
||||||
|
|
||||||
|
Configuring the application
|
||||||
|
---------------------------
|
||||||
|
Before launching the application, you must configure it by editing its
|
||||||
|
configuration file. By default, this file is `/etc/awsiotsdk.conf` but the
|
||||||
|
option `-c` allows the selection of another one.
|
||||||
|
|
||||||
|
You must configure:
|
||||||
|
* `thig_name`: Thing Name of the Shadow this device is associated with.
|
||||||
|
* `host`: Customer specific MQTT HOST.
|
||||||
|
This is your custom endpoint that allows your device to connect to AWS IoT.
|
||||||
|
You can obtain it in your 'AWS IoT Console'.
|
||||||
|
* The certificate settings:
|
||||||
|
* `certs_path`: Absolute path to the certificates directory in the device.
|
||||||
|
* `rootca_filename`: Name of the Root CA file in the configured
|
||||||
|
`certs_path`.
|
||||||
|
* `signed_cert_filename`: Name of the device signed certificate file in
|
||||||
|
the configured `certs_path`.
|
||||||
|
* `private_key_filename`: Name of the device private key file in the
|
||||||
|
configured `certs_path`.
|
||||||
|
* Optionally, any other value in the configuration file.
|
||||||
|
|
||||||
|
Running the application
|
||||||
|
-----------------------
|
||||||
|
Once the settings are properly configured, launch the application:
|
||||||
|
```
|
||||||
|
#> awsiot-sample
|
||||||
|
```
|
||||||
|
You can specify the configuration file with `-c`:
|
||||||
|
```
|
||||||
|
#> awsiot-sample -c <absolute_path_to_configuration_file>
|
||||||
|
```
|
||||||
|
* The application reports its status to the topic
|
||||||
|
`$aws/things/<thing_name>/shadow/update`. Something similar to:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"state" : {
|
||||||
|
"reported" : {
|
||||||
|
"temperature" : 45.971
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"clientToken" : "<thing_name>-3"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Compiling the application
|
||||||
|
-------------------------
|
||||||
|
This demo can be compiled using a Digi Embedded Yocto based toolchain. Make
|
||||||
|
sure to source the corresponding toolchain of the platform you want to build
|
||||||
|
the connector for, e.g:
|
||||||
|
|
||||||
|
```
|
||||||
|
$> . <DEY-toolchain-path>/environment-setup-cortexa7hf-vfp-neon-dey-linux-gnueabi
|
||||||
|
$> make
|
||||||
|
```
|
||||||
|
|
||||||
|
More information about [Digi Embedded Yocto](https://github.com/digi-embedded/meta-digi).
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
Copyright 2017, Digi International Inc.
|
Copyright 2017, Digi International Inc.
|
||||||
|
|
@ -17,4 +85,3 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,3 +47,15 @@ signed_cert_filename = "cert.pem"
|
||||||
# By default, 'privkey.pem'
|
# By default, 'privkey.pem'
|
||||||
private_key_filename = "privkey.pem"
|
private_key_filename = "privkey.pem"
|
||||||
|
|
||||||
|
# Shadow report rate: Frequency at which the device reports its shadow to the
|
||||||
|
# cloud (in seconds).
|
||||||
|
# Its value must be between 1s and a year (31536000s).
|
||||||
|
# By default, 60 seconds.
|
||||||
|
shadow_report_rate = 60
|
||||||
|
|
||||||
|
# Temperature variation: Minimum absolute value of the difference between last
|
||||||
|
# reported temperature and the current value to report to the cloud again
|
||||||
|
# (in C). Its value must be between 0.1C and 10.0C.
|
||||||
|
# By default, 1C.
|
||||||
|
temperature_variation = 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,12 @@
|
||||||
#define SETTING_ROOTCA_NAME "rootca_filename"
|
#define SETTING_ROOTCA_NAME "rootca_filename"
|
||||||
#define SETTING_SCERT_NAME "signed_cert_filename"
|
#define SETTING_SCERT_NAME "signed_cert_filename"
|
||||||
#define SETTING_PRIVKEY_NAME "private_key_filename"
|
#define SETTING_PRIVKEY_NAME "private_key_filename"
|
||||||
|
#define SETTING_SHADOW_REPORT_RATE "shadow_report_rate"
|
||||||
|
#define SETTING_SHADOW_REPORT_RATE_MIN 1 /* second */
|
||||||
|
#define SETTING_SHADOW_REPORT_RATE_MAX (365 * 24 * 60 * 60UL) /* A year */
|
||||||
|
#define SETTING_TEMP_VARIATION "temperature_variation"
|
||||||
|
#define SETTING_TEMP_VARIATION_MIN 0.1 /* C */
|
||||||
|
#define SETTING_TEMP_VARIATION_MAX 10.0 /* C */
|
||||||
|
|
||||||
#define SETTING_UNKNOWN "__unknown"
|
#define SETTING_UNKNOWN "__unknown"
|
||||||
|
|
||||||
|
|
@ -50,7 +56,10 @@ static int cfg_check_client_id(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
static int cfg_check_port(cfg_t *cfg, cfg_opt_t *opt);
|
static int cfg_check_port(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
static int cfg_check_certificates_path(cfg_t *cfg, cfg_opt_t *opt);
|
static int cfg_check_certificates_path(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
static int cfg_check_cert_file(cfg_t *cfg, cfg_opt_t *opt);
|
static int cfg_check_cert_file(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_shadow_report_rate(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_temp_variation(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
static int cfg_check_int_range(cfg_t *cfg, cfg_opt_t *opt, uint32_t min, uint32_t max);
|
static int cfg_check_int_range(cfg_t *cfg, cfg_opt_t *opt, uint32_t min, uint32_t max);
|
||||||
|
static int cfg_check_float_range(cfg_t *cfg, cfg_opt_t *opt, float min, float max);
|
||||||
static int cfg_check_empty_string(cfg_t *cfg, cfg_opt_t *opt);
|
static int cfg_check_empty_string(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
static int cfg_check_string_length(cfg_t *cfg, cfg_opt_t *opt, uint16_t min, uint16_t max);
|
static int cfg_check_string_length(cfg_t *cfg, cfg_opt_t *opt, uint16_t min, uint16_t max);
|
||||||
static int file_exists(const char *const filename);
|
static int file_exists(const char *const filename);
|
||||||
|
|
@ -95,6 +104,9 @@ int parse_configuration(const char *const filename, aws_iot_cfg_t *aws_cfg)
|
||||||
CFG_STR (SETTING_SCERT_NAME, AWS_IOT_CERTIFICATE_FILENAME,CFGF_NONE),
|
CFG_STR (SETTING_SCERT_NAME, AWS_IOT_CERTIFICATE_FILENAME,CFGF_NONE),
|
||||||
CFG_STR (SETTING_PRIVKEY_NAME, AWS_IOT_PRIVATE_KEY_FILENAME,CFGF_NONE),
|
CFG_STR (SETTING_PRIVKEY_NAME, AWS_IOT_PRIVATE_KEY_FILENAME,CFGF_NONE),
|
||||||
|
|
||||||
|
CFG_INT (SETTING_SHADOW_REPORT_RATE, 60, CFGF_NONE),
|
||||||
|
CFG_FLOAT (SETTING_TEMP_VARIATION, 1, CFGF_NONE),
|
||||||
|
|
||||||
/* Needed for unknown settings. */
|
/* Needed for unknown settings. */
|
||||||
CFG_STR (SETTING_UNKNOWN, NULL, CFGF_NONE),
|
CFG_STR (SETTING_UNKNOWN, NULL, CFGF_NONE),
|
||||||
CFG_END()
|
CFG_END()
|
||||||
|
|
@ -119,6 +131,8 @@ int parse_configuration(const char *const filename, aws_iot_cfg_t *aws_cfg)
|
||||||
cfg_set_validate_func(cfg, SETTING_ROOTCA_NAME, cfg_check_cert_file);
|
cfg_set_validate_func(cfg, SETTING_ROOTCA_NAME, cfg_check_cert_file);
|
||||||
cfg_set_validate_func(cfg, SETTING_SCERT_NAME, cfg_check_cert_file);
|
cfg_set_validate_func(cfg, SETTING_SCERT_NAME, cfg_check_cert_file);
|
||||||
cfg_set_validate_func(cfg, SETTING_PRIVKEY_NAME, cfg_check_cert_file);
|
cfg_set_validate_func(cfg, SETTING_PRIVKEY_NAME, cfg_check_cert_file);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_SHADOW_REPORT_RATE, cfg_check_shadow_report_rate);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_TEMP_VARIATION, cfg_check_temp_variation);
|
||||||
|
|
||||||
/* Parse the configuration file. */
|
/* Parse the configuration file. */
|
||||||
switch (cfg_parse(cfg, filename)) {
|
switch (cfg_parse(cfg, filename)) {
|
||||||
|
|
@ -176,6 +190,8 @@ static int fill_aws_iot_config(aws_iot_cfg_t *aws_cfg)
|
||||||
aws_cfg->priv_key_fname = cfg_getstr(cfg, SETTING_PRIVKEY_NAME);
|
aws_cfg->priv_key_fname = cfg_getstr(cfg, SETTING_PRIVKEY_NAME);
|
||||||
if (aws_cfg->priv_key_fname == NULL)
|
if (aws_cfg->priv_key_fname == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
aws_cfg->shadow_report_rate = cfg_getint(cfg, SETTING_SHADOW_REPORT_RATE);
|
||||||
|
aws_cfg->temp_variation = cfg_getfloat(cfg, SETTING_TEMP_VARIATION);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -288,6 +304,38 @@ static int cfg_check_cert_file(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_shadow_report_rate() - Validate shadow report rate value is between
|
||||||
|
* 1s and a year
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_shadow_report_rate(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
return cfg_check_int_range(cfg, opt,
|
||||||
|
SETTING_SHADOW_REPORT_RATE_MIN,
|
||||||
|
SETTING_SHADOW_REPORT_RATE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_temp_variation() - Validate temperature variation value is between
|
||||||
|
* 0.1 and 10.0
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_temp_variation(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
return cfg_check_float_range(cfg, opt,
|
||||||
|
SETTING_TEMP_VARIATION_MIN,
|
||||||
|
SETTING_TEMP_VARIATION_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cfg_check_int_range() - Validate a parameter int value is between the given range
|
* cfg_check_int_range() - Validate a parameter int value is between the given range
|
||||||
*
|
*
|
||||||
|
|
@ -311,6 +359,29 @@ static int cfg_check_int_range(cfg_t *cfg, cfg_opt_t *opt, uint32_t min, uint32_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_float_range() - Validate a parameter float value is between the given range
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
* @min: Minimum value of the parameter.
|
||||||
|
* @max: Maximum value of the parameter.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_float_range(cfg_t *cfg, cfg_opt_t *opt, float min, float max)
|
||||||
|
{
|
||||||
|
float val = cfg_opt_getnfloat(opt, 0);
|
||||||
|
|
||||||
|
if (val > max || val < min) {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Invalid %s (%f): value must be between %f and %f",
|
||||||
|
opt->name, val, min, max);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cfg_check_empty_string() - Validate string is empty
|
* cfg_check_empty_string() - Validate string is empty
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@
|
||||||
* @rootca_fname: Name of the Root CA file
|
* @rootca_fname: Name of the Root CA file
|
||||||
* @signed_cert_fname: Name of the device signed certificate
|
* @signed_cert_fname: Name of the device signed certificate
|
||||||
* @priv_key_fname: Name of the device private key
|
* @priv_key_fname: Name of the device private key
|
||||||
|
* @shadow_report_rate: Frequency at which report system information (seconds)
|
||||||
|
* @temp_variation: Temperature variation between last reported and current
|
||||||
|
* (C) to report again
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *thing_name;
|
char *thing_name;
|
||||||
|
|
@ -54,6 +57,8 @@ typedef struct {
|
||||||
char *rootca_fname;
|
char *rootca_fname;
|
||||||
char *signed_cert_fname;
|
char *signed_cert_fname;
|
||||||
char *priv_key_fname;
|
char *priv_key_fname;
|
||||||
|
uint32_t shadow_report_rate;
|
||||||
|
uint16_t temp_variation;
|
||||||
} aws_iot_cfg_t;
|
} aws_iot_cfg_t;
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,298 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Digi International Inc.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <aws_iot_config.h>
|
||||||
|
#include <aws_iot_log.h>
|
||||||
|
#include <aws_iot_shadow_interface.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aws_config.h"
|
||||||
|
#include "aws_control.h"
|
||||||
|
#include "device_control.h"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E C L A R A T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
static void shadow_update_status_callback(const char *pThingName,
|
||||||
|
ShadowActions_t action,
|
||||||
|
Shadow_Ack_Status_t status,
|
||||||
|
const char *pReceivedJsonDocument,
|
||||||
|
void *pContextData);
|
||||||
|
static void disconnect_callback(AWS_IoT_Client *mqtt_client, void *data);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
G L O B A L V A R I A B L E S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
aws_iot_cfg_t aws_cfg;
|
||||||
|
device_shadow_t *device_shadow;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* initialize_shadow_client() - Initialize AWS IoT Device SDK
|
||||||
|
*
|
||||||
|
* @mqtt_client: MQTT client.
|
||||||
|
* @aws_config: Absolute path of the configuration file to use.
|
||||||
|
* NULL to use the default one (/etc/awsiotsdk.conf).
|
||||||
|
*
|
||||||
|
* Return: An IoT error code defining successful/failed initialization.
|
||||||
|
*/
|
||||||
|
IoT_Error_t initialize_shadow_client(AWS_IoT_Client *mqtt_client, const char *config_file)
|
||||||
|
{
|
||||||
|
ShadowInitParameters_t shadow_init_params = ShadowInitParametersDefault;
|
||||||
|
IoT_Error_t rc = FAILURE;
|
||||||
|
char root_ca[PATH_MAX + 1];
|
||||||
|
char client_crt[PATH_MAX + 1];
|
||||||
|
char client_key[PATH_MAX + 1];
|
||||||
|
|
||||||
|
if (parse_configuration(config_file ? config_file : AWS_IOT_CONFIG_FILE, &aws_cfg) != 0)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
snprintf(root_ca, PATH_MAX + 1, "%s/%s", aws_cfg.certs_path, aws_cfg.rootca_fname);
|
||||||
|
snprintf(client_crt, PATH_MAX + 1, "%s/%s", aws_cfg.certs_path, aws_cfg.signed_cert_fname);
|
||||||
|
snprintf(client_key, PATH_MAX + 1, "%s/%s", aws_cfg.certs_path, aws_cfg.priv_key_fname);
|
||||||
|
|
||||||
|
IOT_DEBUG("Root CA file: %s", root_ca);
|
||||||
|
IOT_DEBUG("Device signed certificate file: %s", client_crt);
|
||||||
|
IOT_DEBUG("Device private key file: %s", client_key);
|
||||||
|
|
||||||
|
/* Initialize the MQTT client */
|
||||||
|
shadow_init_params.pHost = aws_cfg.host;
|
||||||
|
shadow_init_params.port = aws_cfg.port;
|
||||||
|
shadow_init_params.pRootCA = root_ca;
|
||||||
|
shadow_init_params.pClientCRT = client_crt;
|
||||||
|
shadow_init_params.pClientKey = client_key;
|
||||||
|
shadow_init_params.enableAutoReconnect = false; /* Enable later */
|
||||||
|
|
||||||
|
IOT_INFO("Initializing MQTT...");
|
||||||
|
rc = aws_iot_shadow_init(mqtt_client, &shadow_init_params);
|
||||||
|
if (rc != SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = aws_iot_mqtt_set_disconnect_handler(mqtt_client,
|
||||||
|
disconnect_callback, NULL);
|
||||||
|
if (rc != SUCCESS) {
|
||||||
|
IOT_ERROR("Unable to set MQTT disconnect handler, error: %d",
|
||||||
|
rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable Auto Reconnect functionality.
|
||||||
|
* Min and max time of exponential backoff are set in 'aws_iot_config.h':
|
||||||
|
* #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
|
||||||
|
* #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
|
||||||
|
*/
|
||||||
|
rc = aws_iot_shadow_set_autoreconnect_status(mqtt_client, true);
|
||||||
|
if (rc != SUCCESS)
|
||||||
|
IOT_ERROR("Unable to enable auto-reconnect, error: %d", rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for shadow updates getting out of sync:
|
||||||
|
*
|
||||||
|
* WARN: shadow_delta_callback L#504 Old Delta Message received -
|
||||||
|
* Ignoring rx: 40408 local: 40408
|
||||||
|
*
|
||||||
|
* See discussion here:
|
||||||
|
* https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/32
|
||||||
|
*/
|
||||||
|
aws_iot_shadow_disable_discard_old_delta_msgs();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connect_shadow_client() - Establish MQTT connection
|
||||||
|
*
|
||||||
|
* @mqtt_client: MQTT client.
|
||||||
|
*
|
||||||
|
* Return: An IoT error code defining successful/failed connection.
|
||||||
|
*/
|
||||||
|
IoT_Error_t connect_shadow_client(AWS_IoT_Client *mqtt_client)
|
||||||
|
{
|
||||||
|
ShadowConnectParameters_t conn_params = ShadowConnectParametersDefault;
|
||||||
|
|
||||||
|
conn_params.pMyThingName = aws_cfg.thing_name;
|
||||||
|
conn_params.pMqttClientId = aws_cfg.client_id;
|
||||||
|
conn_params.mqttClientIdLen = (uint16_t) strlen(aws_cfg.client_id);
|
||||||
|
conn_params.deleteActionHandler = NULL;
|
||||||
|
|
||||||
|
IOT_INFO("Shadow connecting...");
|
||||||
|
return aws_iot_shadow_connect(mqtt_client, &conn_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disconnect_shadow_client() - Close MQTT connection
|
||||||
|
*
|
||||||
|
* @mqtt_client: MQTT client.
|
||||||
|
*
|
||||||
|
* Return: An IoT error code defining successful/failed disconnect status.
|
||||||
|
*/
|
||||||
|
IoT_Error_t disconnect_shadow_client(AWS_IoT_Client *mqtt_client)
|
||||||
|
{
|
||||||
|
IoT_Error_t rc = FAILURE;
|
||||||
|
|
||||||
|
IOT_INFO("Disconnecting...");
|
||||||
|
|
||||||
|
rc = aws_iot_shadow_disconnect(mqtt_client);
|
||||||
|
|
||||||
|
free_configuration();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize_shadow() - Initialize device Shadow
|
||||||
|
*
|
||||||
|
* @mqtt_client: MQTT client.
|
||||||
|
* @dev_shadow: Device shadow.
|
||||||
|
*
|
||||||
|
* Return: An IoT error code defining successful/failed initialization.
|
||||||
|
*/
|
||||||
|
IoT_Error_t initialize_shadow(AWS_IoT_Client *mqtt_client,
|
||||||
|
device_shadow_t *dev_shadow)
|
||||||
|
{
|
||||||
|
device_shadow = dev_shadow;
|
||||||
|
|
||||||
|
device_shadow->temp_handler.cb = NULL;
|
||||||
|
device_shadow->temp_handler.pKey = ATTR_TEMPERATURE;
|
||||||
|
device_shadow->temp_handler.pData = &(device_shadow->temp);
|
||||||
|
device_shadow->temp_handler.type = SHADOW_JSON_DOUBLE;
|
||||||
|
|
||||||
|
device_shadow->temp = 0;
|
||||||
|
device_shadow->temp_update = 0;
|
||||||
|
|
||||||
|
device_shadow->aws_config = &aws_cfg;
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update_shadow() - Update thing shadow.
|
||||||
|
*
|
||||||
|
* @mqtt_client: MQTT client.
|
||||||
|
*
|
||||||
|
* Return: An IoT error code defining successful/failed update action.
|
||||||
|
*/
|
||||||
|
IoT_Error_t update_shadow(AWS_IoT_Client *mqtt_client)
|
||||||
|
{
|
||||||
|
char json_doc_buf[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
|
||||||
|
size_t size_json_doc_buf = sizeof(json_doc_buf) / sizeof(json_doc_buf[0]);
|
||||||
|
IoT_Error_t rc = FAILURE;
|
||||||
|
|
||||||
|
rc = aws_iot_shadow_init_json_document(json_doc_buf, size_json_doc_buf);
|
||||||
|
if (rc != SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = aws_iot_shadow_add_reported(json_doc_buf, size_json_doc_buf,
|
||||||
|
1,
|
||||||
|
&(device_shadow->temp_handler));
|
||||||
|
if (rc != SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = aws_iot_finalize_json_document(json_doc_buf, size_json_doc_buf);
|
||||||
|
if (rc != SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return aws_iot_shadow_update(mqtt_client, aws_cfg.thing_name,
|
||||||
|
json_doc_buf,
|
||||||
|
shadow_update_status_callback,
|
||||||
|
(void *) device_shadow, 4, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shadow_update_status_callback() - AWS IoT Device SDK update status callback
|
||||||
|
*
|
||||||
|
* Callback to inform of the response from the AWS IoT Shadow service.
|
||||||
|
*
|
||||||
|
* @pThingName: Thing name of the shadow to be updated.
|
||||||
|
* @action: The response of the action.
|
||||||
|
* @status: Update action status: accepted, rejected or time out.
|
||||||
|
* @pReceivedJsonDocument: Received JSON document.
|
||||||
|
* @pContextData: Data for the callback. NULL if not used.
|
||||||
|
*/
|
||||||
|
static void shadow_update_status_callback(const char *pThingName,
|
||||||
|
ShadowActions_t action,
|
||||||
|
Shadow_Ack_Status_t status,
|
||||||
|
const char *pReceivedJsonDocument,
|
||||||
|
void *pContextData)
|
||||||
|
{
|
||||||
|
device_shadow_t *dev_shadow = NULL;
|
||||||
|
|
||||||
|
IOT_UNUSED(pThingName);
|
||||||
|
IOT_UNUSED(pReceivedJsonDocument);
|
||||||
|
|
||||||
|
if (action != SHADOW_UPDATE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev_shadow = (device_shadow_t *)pContextData;
|
||||||
|
|
||||||
|
switch(status) {
|
||||||
|
case SHADOW_ACK_TIMEOUT:
|
||||||
|
IOT_INFO("Shadow update timeout");
|
||||||
|
break;
|
||||||
|
case SHADOW_ACK_REJECTED:
|
||||||
|
IOT_INFO("Shadow update rejected");
|
||||||
|
break;
|
||||||
|
case SHADOW_ACK_ACCEPTED:
|
||||||
|
IOT_INFO("Shadow update accepted");
|
||||||
|
dev_shadow->temp_update = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disconnect_callback() - AWS IoT Device SDK disconnect callback
|
||||||
|
*
|
||||||
|
* It is called whenever the client disconnects with error.
|
||||||
|
*
|
||||||
|
* @mqtt_client: MQTT client.
|
||||||
|
* @data: Reference to the data to be passed as argument when
|
||||||
|
* disconnect handler is called
|
||||||
|
*/
|
||||||
|
static void disconnect_callback(AWS_IoT_Client *mqtt_client, void *data)
|
||||||
|
{
|
||||||
|
IoT_Error_t rc = FAILURE;
|
||||||
|
|
||||||
|
IOT_WARN("MQTT Disconnect");
|
||||||
|
|
||||||
|
if (mqtt_client == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IOT_UNUSED(data);
|
||||||
|
|
||||||
|
if (aws_iot_is_autoreconnect_enabled(mqtt_client)) {
|
||||||
|
IOT_INFO("Auto-reconnect enabled. Reconnecting attempt will start now");
|
||||||
|
} else {
|
||||||
|
IOT_WARN("Auto-reconnect not enabled. Starting manual reconnect...");
|
||||||
|
rc = aws_iot_mqtt_attempt_reconnect(mqtt_client);
|
||||||
|
if (rc == NETWORK_RECONNECTED) {
|
||||||
|
IOT_WARN("Manual Reconnect successful");
|
||||||
|
} else {
|
||||||
|
IOT_WARN("Manual Reconnect failed, error: %d", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Digi International Inc.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AWS_CONTROL_H_
|
||||||
|
#define AWS_CONTROL_H_
|
||||||
|
|
||||||
|
#include <aws_iot_mqtt_client.h>
|
||||||
|
#include <aws_iot_shadow_json.h>
|
||||||
|
|
||||||
|
#include "aws_config.h"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#define ATTR_TEMPERATURE "temperature"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D A T A T Y P E S D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* device_shadow_t - Device Shadow type
|
||||||
|
*
|
||||||
|
* @temp: Last temperature reported (C)
|
||||||
|
* @temp_handler: Temperature handler
|
||||||
|
* @temp_update: Temperature value locally updated
|
||||||
|
* @update_required: Update shadow immediately
|
||||||
|
* @aws_config: AWS IoT Decive SDK configuration struct
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
double temp;
|
||||||
|
jsonStruct_t temp_handler;
|
||||||
|
unsigned int temp_update;
|
||||||
|
unsigned int update_required;
|
||||||
|
aws_iot_cfg_t *aws_config;
|
||||||
|
} device_shadow_t;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E C L A R A T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
IoT_Error_t initialize_shadow_client(AWS_IoT_Client *mqtt_client, const char *config_file);
|
||||||
|
IoT_Error_t connect_shadow_client(AWS_IoT_Client *mqtt_client);
|
||||||
|
IoT_Error_t disconnect_shadow_client(AWS_IoT_Client *mqtt_client);
|
||||||
|
IoT_Error_t initialize_shadow(AWS_IoT_Client *mqtt_client, device_shadow_t *device_shadow);
|
||||||
|
IoT_Error_t update_shadow(AWS_IoT_Client *mqtt_client);
|
||||||
|
|
||||||
|
#endif /* AWS_CONTROL_H_ */
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Digi International Inc.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <aws_iot_log.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "device_control.h"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#define MAX_LENGTH 256
|
||||||
|
|
||||||
|
#define FILE_CPU_TEMP "/sys/class/thermal/thermal_zone0/temp"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E C L A R A T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
static long read_file(const char * path, char *buffer, long bytes_to_read);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* get_cpu_temp() - Get the CPU temperature of the system
|
||||||
|
*
|
||||||
|
* Return: The CPU temperature in C, -1 if error.
|
||||||
|
*/
|
||||||
|
double get_cpu_temp(void)
|
||||||
|
{
|
||||||
|
char file_data[MAX_LENGTH] = {0};
|
||||||
|
double temperature ;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (read_file(FILE_CPU_TEMP, file_data, MAX_LENGTH) <= 0) {
|
||||||
|
IOT_ERROR("Error reading CPU temperature file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sscanf(file_data, "%lf", &temperature);
|
||||||
|
if (result < 1) {
|
||||||
|
IOT_ERROR("Error getting CPU temperature: not enough fields");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return temperature / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read_file() - Read the given file and returns its contents
|
||||||
|
*
|
||||||
|
* @path: Absolute path of the file to read.
|
||||||
|
* @buffer: Buffer to store the contents of the file.
|
||||||
|
* @bytes_to_read: The number of bytes to read (including the terminating
|
||||||
|
* null byte).
|
||||||
|
*
|
||||||
|
* Return: The number of read bytes (including the terminating null byte), -1 on
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
static long read_file(const char * path, char *buffer, long bytes_to_read)
|
||||||
|
{
|
||||||
|
FILE *fd = NULL;
|
||||||
|
long read_size = 0;
|
||||||
|
|
||||||
|
if (access(path, R_OK) != 0) {
|
||||||
|
IOT_DEBUG("File cannot be read: %s", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fd = fopen(path, "rb")) == NULL) {
|
||||||
|
IOT_DEBUG("fopen error: %s", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fgets(buffer, bytes_to_read, fd) == NULL) {
|
||||||
|
IOT_DEBUG("fgets error: %s", path);
|
||||||
|
read_size = -1;
|
||||||
|
} else {
|
||||||
|
read_size = strlen(buffer) + 1;
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
return read_size;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Digi International Inc.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEVICE_CONTROL_H_
|
||||||
|
#define DEVICE_CONTROL_H_
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E C L A R A T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
double get_cpu_temp(void);
|
||||||
|
|
||||||
|
#endif /* DEVICE_CONTROL_H_ */
|
||||||
|
|
@ -18,24 +18,34 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <aws_iot_log.h>
|
#include <aws_iot_log.h>
|
||||||
|
#include <aws_iot_version.h>
|
||||||
|
#include <aws_iot_shadow_interface.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "aws_config.h"
|
#include "aws_config.h"
|
||||||
|
#include "aws_control.h"
|
||||||
#include "daemonize.h"
|
#include "daemonize.h"
|
||||||
|
#include "device_control.h"
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
D E F I N I T I O N S
|
D E F I N I T I O N S
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
#define STRINGIFY(x) #x
|
||||||
|
#define TOSTRING(x) STRINGIFY(x)
|
||||||
|
|
||||||
#define VERSION "0.1" GIT_REVISION
|
#define VERSION "0.1" GIT_REVISION
|
||||||
|
#define AWS_IOT_VERSION TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR) "." TOSTRING(VERSION_PATCH) "-" VERSION_TAG
|
||||||
|
|
||||||
#define USAGE \
|
#define USAGE \
|
||||||
"AWS IoT Device SDK demo.\n" \
|
"AWS IoT Device SDK demo.\n" \
|
||||||
"Copyright(c) Digi International Inc.\n" \
|
"Copyright(c) Digi International Inc.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Version: %s\n" \
|
"Version: %s\n" \
|
||||||
|
"AWS IoT SDK Version: " AWS_IOT_VERSION "\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Usage: %s [options]\n\n" \
|
"Usage: %s [options]\n\n" \
|
||||||
" -d --daemon Daemonize the process\n" \
|
" -d --daemon Daemonize the process\n" \
|
||||||
|
|
@ -58,6 +68,7 @@ static void usage(char const *const name);
|
||||||
G L O B A L V A R I A B L E S
|
G L O B A L V A R I A B L E S
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
static volatile int stop = 0;
|
static volatile int stop = 0;
|
||||||
|
static AWS_IoT_Client mqtt_client;
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
F U N C T I O N D E F I N I T I O N S
|
F U N C T I O N D E F I N I T I O N S
|
||||||
|
|
@ -125,19 +136,82 @@ done:
|
||||||
*/
|
*/
|
||||||
static int start_aws_iot(const char *config_file)
|
static int start_aws_iot(const char *config_file)
|
||||||
{
|
{
|
||||||
int result = EXIT_SUCCESS;
|
IoT_Error_t rc = FAILURE;
|
||||||
aws_iot_cfg_t aws_cfg;
|
device_shadow_t device_shadow;
|
||||||
|
time_t time_start;
|
||||||
|
|
||||||
add_sigkill_signal();
|
add_sigkill_signal();
|
||||||
|
|
||||||
if (parse_configuration(config_file ? config_file : AWS_IOT_CONFIG_FILE, &aws_cfg) != 0)
|
rc = initialize_shadow_client(&mqtt_client, config_file);
|
||||||
return EXIT_FAILURE;;
|
if (rc != SUCCESS) {
|
||||||
|
IOT_ERROR("Cannot initialize Shadow client, error: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = connect_shadow_client(&mqtt_client);
|
||||||
|
if (rc != SUCCESS) {
|
||||||
|
IOT_ERROR("Unable to connect, error: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = initialize_shadow(&mqtt_client, &device_shadow);
|
||||||
|
if (rc != SUCCESS) {
|
||||||
|
IOT_ERROR("Unable to initialize device Shadow, error: %d", rc);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_start = time(NULL);
|
||||||
|
/* Loop and publish shadow changes */
|
||||||
|
while (rc == NETWORK_ATTEMPTING_RECONNECT ||
|
||||||
|
rc == NETWORK_RECONNECTED ||
|
||||||
|
rc == SUCCESS ||
|
||||||
|
!check_stop()) {
|
||||||
|
aws_iot_cfg_t *aws_cfg = device_shadow.aws_config;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
rc = aws_iot_mqtt_yield(&mqtt_client, 200);
|
||||||
|
|
||||||
|
if (rc == NETWORK_ATTEMPTING_RECONNECT) {
|
||||||
|
sleep(1);
|
||||||
|
/* If the client is attempting to reconnect,
|
||||||
|
* skip the rest of the loop */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = get_cpu_temp();
|
||||||
|
device_shadow.temp_update = (t <= (device_shadow.temp - aws_cfg->temp_variation) ||
|
||||||
|
t >= (device_shadow.temp + aws_cfg->temp_variation));
|
||||||
|
|
||||||
|
if (device_shadow.temp_update ||
|
||||||
|
(time(NULL) - time_start) >= aws_cfg->shadow_report_rate) {
|
||||||
|
device_shadow.temp = t;
|
||||||
|
|
||||||
|
IOT_INFO("\n=========================================");
|
||||||
|
IOT_INFO("Updating shadow...");
|
||||||
|
if (device_shadow.temp_update)
|
||||||
|
IOT_INFO(
|
||||||
|
"Temperature variation greater than %dC\n",
|
||||||
|
aws_cfg->temp_variation);
|
||||||
|
|
||||||
|
IOT_INFO("Temperature: %fC", t);
|
||||||
|
IOT_INFO("=========================================\n");
|
||||||
|
|
||||||
|
rc = update_shadow(&mqtt_client);
|
||||||
|
|
||||||
|
if ((time(NULL) - time_start) >= aws_cfg->shadow_report_rate)
|
||||||
|
time_start = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
} while (!check_stop());
|
}
|
||||||
|
|
||||||
return result;
|
done:
|
||||||
|
if (rc != SUCCESS) {
|
||||||
|
IOT_ERROR("Error occurred in the loop: %d", rc);
|
||||||
|
graceful_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -147,6 +221,14 @@ static int start_aws_iot(const char *config_file)
|
||||||
*/
|
*/
|
||||||
static int check_stop(void)
|
static int check_stop(void)
|
||||||
{
|
{
|
||||||
|
if (stop) {
|
||||||
|
IoT_Error_t rc = disconnect_shadow_client(&mqtt_client);
|
||||||
|
if (rc != SUCCESS) {
|
||||||
|
IOT_ERROR("Disconnect error: %d", rc);
|
||||||
|
stop = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return stop;
|
return stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue