diff --git a/iotconnect-sdk/include/iotconnect.h b/iotconnect-sdk/include/iotconnect.h index b007130..dfd268d 100644 --- a/iotconnect-sdk/include/iotconnect.h +++ b/iotconnect-sdk/include/iotconnect.h @@ -29,14 +29,18 @@ typedef enum { typedef void (*IotConnectStatusCallback)(IotconnectConnectionStatus data); + + typedef struct { char *env; // Environment name. Contact your representative for details. char *cpid; // Settings -> Company Profile. char *duid; // Name of the device. IotclOtaCallback ota_cb; // callback for OTA events. IotclCommandCallback cmd_cb; // callback for command events. + IotcltwinrecivCallback twin_msg_cb; IotclMessageCallback msg_cb; // callback for ALL messages, including the specific ones like cmd or ota callback. IotConnectStatusCallback status_cb; // callback for connection status + } IotconnectClientConfig; diff --git a/iotconnect-sdk/nrf-layer-lib/include/iotconnect_mqtt.h b/iotconnect-sdk/nrf-layer-lib/include/iotconnect_mqtt.h index 71f892c..0b33f8e 100644 --- a/iotconnect-sdk/nrf-layer-lib/include/iotconnect_mqtt.h +++ b/iotconnect-sdk/nrf-layer-lib/include/iotconnect_mqtt.h @@ -18,10 +18,13 @@ extern "C" { typedef void (*IotconnectMqttOnDataCallback)(const uint8_t *data, size_t len, const char *topic); +typedef void (*IotconnectMqttTwinDataCallback)(const uint8_t *data, size_t len, const char *topic); + typedef struct { int tls_verify; // NONE = 0, OPTIONAL = 1, REQUIRED = 2 const char *env; // Environment name. Contact your representative for details. Same as telemetry config. IotconnectMqttOnDataCallback data_cb; // callback for OTA events. + IotconnectMqttTwinDataCallback twin_cb;//callback twin event. IotConnectStatusCallback status_cb; // callback for command events. } IotconnectMqttConfig; diff --git a/iotconnect-sdk/nrf-layer-lib/src/iotconnect_mqtt.c b/iotconnect-sdk/nrf-layer-lib/src/iotconnect_mqtt.c index 7f49773..fc6d544 100644 --- a/iotconnect-sdk/nrf-layer-lib/src/iotconnect_mqtt.c +++ b/iotconnect-sdk/nrf-layer-lib/src/iotconnect_mqtt.c @@ -325,11 +325,19 @@ static void mqtt_evt_handler(struct mqtt_client *const c, printk("MQTT PUBLISH result=%d len=%d\n", evt->result, p->message.payload.len); err = get_event_payload(c, p->message.payload.len); if (err >= 0) { - - if (config->data_cb) { - config->data_cb(payload_buf, p->message.payload.len, p->message.topic.topic.utf8); + if(! strncmp(p->message.topic.topic.utf8,"$iothub/twin/res/",17)){ + if (config->twin_cb) { + config->twin_cb(payload_buf, p->message.payload.len, p->message.topic.topic.utf8); + } else { + printk("Error: no mqtt twin_cb configured\n"); + } } else { - printk("Error: no mqtt data_cb configured\n"); + if (config->data_cb) { + config->data_cb(payload_buf, p->message.payload.len, p->message.topic.topic.utf8); + } else { + printk("Error: no mqtt data_cb configured\n"); + } + } } else { @@ -434,22 +442,22 @@ bool iotc_nrf_mqtt_init(IotconnectMqttConfig *c, IotclSyncResponse *sr) { config = c; if (!client_init()) { - return false; + return -1; } err = mqtt_connect(&client); if (err != 0) { printk("ERROR: mqtt_connect %d\n", err); - return false; + return -2; } err = fds_init(&client); if (err != 0) { printk("ERROR: fds_init %d\n", err); - return false; + return -3; } - return true; + return 1; } diff --git a/iotconnect-sdk/src/iotconnect.c b/iotconnect-sdk/src/iotconnect.c index 3dfb88e..8267e72 100644 --- a/iotconnect-sdk/src/iotconnect.c +++ b/iotconnect-sdk/src/iotconnect.c @@ -37,6 +37,12 @@ static IotconnectMqttConfig mqtt_config = {0}; static char send_buf[MAXLINE + 1]; static bool sdk_initialized = false; +char* const twinPropertyPubTopic ="$iothub/twin/PATCH/properties/reported/?$rid=1"; +char* const twinPropertySubTopic ="$iothub/twin/PATCH/properties/desired/#"; +char* const twinResponsePubTopic ="$iothub/twin/GET/?$rid=0"; +char* const twinResponseSubTopic ="$iothub/twin/res/#"; + + static void dump_response(const char *message, IotconnectNrfHttpResponse *response) { printk("%s", message); if (response->raw_response) { @@ -182,7 +188,20 @@ void iotc_on_mqtt_data(const uint8_t *data, size_t len, const char *topic) { str[len] = 0; printk("event>>> %s\n", str); if (!iotcl_process_event(str)) { - printk("Error encountered while processing %s\n", str); + printk("Error encountered while processing command ::%s\n", str); + } + free(str); +} + +void iotc_twin_mqtt_data(const uint8_t *data, size_t len, const char *topic) { + (void) topic; // ignore topic for now + char *str = malloc(len + 1); + char *SMS; + memcpy(str, data, len); + str[len] = 0; + printk("event>>> %s\n", str); + if (!iotcl_process_twin_event(str)) { + printk("Error encountered while processing Twin ::%s\n", str); } free(str); } @@ -208,6 +227,29 @@ void iotconnect_sdk_send_packet(const char *data) { } } +void iotconnect_sdk_send_twin_update_packet(const char *data) { + if (0 != iotc_nrf_mqtt_publish(&client, twinPropertyPubTopi, MQTT_QOS_0_AT_MOST_ONCE, data, strlen(data))) { + printk("\n\t Device_twin_Data Publish failure"); + } +} + +//This will iotconnect_update_twin property to IoTConnect +void iotconnect_update_twin(char *key,char *value){ + char *Twin_Json_Data; + cJSON *root; + root = cJSON_CreateObject(); + + cJSON_AddStringToObject(root, key, value); + Twin_Json_Data = cJSON_PrintUnformatted(root); + + printk("json format of Twin_Json_Data = %s",Twin_Json_Data); + iotconnect_sdk_send_twin_update_packet(Twin_Json_Data); + + cJSON_Delete(root); + free(Twin_Json_Data); +} + + static void on_message_intercept(IotclEventData data, IotConnectEventType type) { switch (type) { case ON_FORCE_SYNC: @@ -289,6 +331,7 @@ int iotconnect_sdk_init() { lib_config.telemetry.dtg = sync_response->dtg;; lib_config.event_functions.ota_cb = config.ota_cb; lib_config.event_functions.cmd_cb = config.cmd_cb; + lib_config.event_functions.twin_msg_cb = config.twin_msg_cb; // intercept internal processing and forward to client lib_config.event_functions.msg_cb = on_message_intercept; @@ -301,6 +344,7 @@ int iotconnect_sdk_init() { } mqtt_config.tls_verify = CONFIG_PEER_VERIFY; mqtt_config.data_cb = iotc_on_mqtt_data; + mqtt_config.twin_cb = iotc_twin_mqtt_data; mqtt_config.status_cb = on_iotconnect_status; if (!iotc_nrf_mqtt_init(&mqtt_config, sync_response)) { diff --git a/samples/iotc-basic/src/main.c b/samples/iotc-basic/src/main.c index d0d839f..0667378 100644 --- a/samples/iotc-basic/src/main.c +++ b/samples/iotc-basic/src/main.c @@ -189,6 +189,28 @@ static void on_ota(IotclEventData data) { } } +static void on_twin_command(IotclEventData payload) +{ + + TwinStrings *result = iotcl_get_twin_key_and_value(payload); + + /* + Type : Public Method "iotconnect_update_twin()" + Usage : Upate the twin reported property + Output : + Input : "key" and "value" as below + // String key = "<< Desired property key >>"; // Desired proeprty key received from Twin callback message + // String value = "<< Desired Property value >>"; // Value of respective desired property + */ + iotconnect_update_twin(result->key,result->value); + + // Don't forget to free the allocated memory + free(result); + +} + + + static void on_command(IotclEventData data) { const char *command = iotcl_clone_command(data); if (NULL != command) { @@ -663,6 +685,7 @@ void main(void) { config->cmd_cb = on_command; config->ota_cb = on_ota; config->status_cb = on_connection_status; + config->twin_msg_cb = on_twin_command; #pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" diff --git a/samples/iotc-sensors-gps/src/main.c b/samples/iotc-sensors-gps/src/main.c index 57d6986..f054bd7 100644 --- a/samples/iotc-sensors-gps/src/main.c +++ b/samples/iotc-sensors-gps/src/main.c @@ -24,7 +24,7 @@ #include "buzzer.h" #else #define ui_leds_init() -#define ui_led_set_rgb(a,b,c) (void) (a,b,c) +#define ui_led_set_rgb(a,b,c) (void) (a,b,c) #define ui_buzzer_init() #endif #include "iotconnect.h" @@ -212,6 +212,26 @@ static void on_ota(IotclEventData data) { } } +static void on_twin_command(IotclEventData payload) +{ + + TwinStrings *result = iotcl_get_twin_key_and_value(payload); + + /* + Type : Public Method "iotconnect_update_twin()" + Usage : Upate the twin reported property + Output : + Input : "key" and "value" as below + // String key = "<< Desired property key >>"; // Desired proeprty key received from Twin callback message + // String value = "<< Desired Property value >>"; // Value of respective desired property + */ + iotconnect_update_twin(result->key,result->value); + + // Don't forget to free the allocated memory + free(result); + +} + static void on_command(IotclEventData data) { char *command = iotcl_clone_command(data); if (NULL != command) { @@ -223,6 +243,7 @@ static void on_command(IotclEventData data) { } } + static void on_connection_status(IotconnectConnectionStatus status) { // Add your own status handling switch (status) { @@ -917,6 +938,8 @@ void main(void) { config->cmd_cb = on_command; config->ota_cb = on_ota; config->status_cb = on_connection_status; + config->twin_msg_cb = on_twin_command; + #pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" diff --git a/scripts/setup-iotc-c-lib.sh b/scripts/setup-iotc-c-lib.sh index 219e684..dd00f3b 100755 --- a/scripts/setup-iotc-c-lib.sh +++ b/scripts/setup-iotc-c-lib.sh @@ -2,6 +2,6 @@ set -e -git clone --depth 1 --branch v2.0.0 git://github.com/Avnet/iotc-c-lib.git +git clone --depth 1 --branch iotc-c-lib-patch https://github.com/avnet-iotconnect/iotc-c-lib.git test -d iotc-c-lib cp -f common/iotc-c-lib-overlay/CMakeLists.txt iotc-c-lib/