Parse sync response from server
This commit is contained in:
		@@ -2,6 +2,7 @@ use crate::app_config::AppConfig;
 | 
				
			|||||||
use crate::crypto::pki;
 | 
					use crate::crypto::pki;
 | 
				
			||||||
use crate::devices::device::{DeviceId, DeviceInfo};
 | 
					use crate::devices::device::{DeviceId, DeviceInfo};
 | 
				
			||||||
use crate::energy::energy_actor;
 | 
					use crate::energy::energy_actor;
 | 
				
			||||||
 | 
					use crate::energy::energy_actor::RelaySyncStatus;
 | 
				
			||||||
use crate::server::custom_error::HttpResult;
 | 
					use crate::server::custom_error::HttpResult;
 | 
				
			||||||
use crate::server::WebEnergyActor;
 | 
					use crate::server::WebEnergyActor;
 | 
				
			||||||
use actix_web::{web, HttpResponse};
 | 
					use actix_web::{web, HttpResponse};
 | 
				
			||||||
@@ -138,6 +139,11 @@ struct Claims {
 | 
				
			|||||||
    info: DeviceInfo,
 | 
					    info: DeviceInfo,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize)]
 | 
				
			||||||
 | 
					struct SyncResult {
 | 
				
			||||||
 | 
					    relays: Vec<RelaySyncStatus>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Synchronize device
 | 
					/// Synchronize device
 | 
				
			||||||
pub async fn sync_device(body: web::Json<SyncRequest>, actor: WebEnergyActor) -> HttpResult {
 | 
					pub async fn sync_device(body: web::Json<SyncRequest>, actor: WebEnergyActor) -> HttpResult {
 | 
				
			||||||
    // First, we need to extract device kid from query
 | 
					    // First, we need to extract device kid from query
 | 
				
			||||||
@@ -199,9 +205,9 @@ pub async fn sync_device(body: web::Json<SyncRequest>, actor: WebEnergyActor) ->
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let res = actor
 | 
					    let relays = actor
 | 
				
			||||||
        .send(energy_actor::SynchronizeDevice(device.id, c.claims.info))
 | 
					        .send(energy_actor::SynchronizeDevice(device.id, c.claims.info))
 | 
				
			||||||
        .await??;
 | 
					        .await??;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(HttpResponse::Ok().json(res))
 | 
					    Ok(HttpResponse::Ok().json(SyncResult { relays }))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								esp32_device/.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								esp32_device/.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -49,6 +49,7 @@
 | 
				
			|||||||
    "regex": "c",
 | 
					    "regex": "c",
 | 
				
			||||||
    "stdlib.h": "c",
 | 
					    "stdlib.h": "c",
 | 
				
			||||||
    "secure_api.h": "c",
 | 
					    "secure_api.h": "c",
 | 
				
			||||||
    "jwt.h": "c"
 | 
					    "jwt.h": "c",
 | 
				
			||||||
 | 
					    "sync_response.h": "c"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
idf_component_register(SRCS "jwt.c" "secure_api.c" "http_client.c" "ethernet.c" "unsecure_api.c" "system.c" "crypto.c" "random.c" "storage.c" "main.c"
 | 
					idf_component_register(SRCS "sync_response.c" "jwt.c" "secure_api.c" "http_client.c" "ethernet.c" "unsecure_api.c" "system.c" "crypto.c" "random.c" "storage.c" "main.c"
 | 
				
			||||||
                        "dev_name.c"
 | 
					                        "dev_name.c"
 | 
				
			||||||
                    INCLUDE_DIRS ".")
 | 
					                    INCLUDE_DIRS ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,3 +44,8 @@
 | 
				
			|||||||
 * Secure origin len
 | 
					 * Secure origin len
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define SEC_ORIG_LEN 255
 | 
					#define SEC_ORIG_LEN 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Interval of time (in seconds) between two synchronisations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define SYNC_TIME_INTERVAL 5
 | 
				
			||||||
@@ -21,6 +21,8 @@ void app_main(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ESP_LOGI(TAG, "SolarEnergy WT32-ETH01 device");
 | 
					    ESP_LOGI(TAG, "SolarEnergy WT32-ETH01 device");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO : turn off all relays
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initialize storage
 | 
					    // Initialize storage
 | 
				
			||||||
    if (storage_init() == false)
 | 
					    if (storage_init() == false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -167,22 +169,40 @@ void app_main(void)
 | 
				
			|||||||
    // Main loop
 | 
					    // Main loop
 | 
				
			||||||
    ESP_LOGI(TAG, "Starting main loop");
 | 
					    ESP_LOGI(TAG, "Starting main loop");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO : implement more properly
 | 
					    size_t fails = 0;
 | 
				
			||||||
    while (true)
 | 
					    while (true)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!secure_api_sync_device())
 | 
					        sync_response *res = secure_api_sync_device();
 | 
				
			||||||
 | 
					        if (!res)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            fails += 1;
 | 
				
			||||||
            ESP_LOGE(TAG, "Failed to synchronise device!");
 | 
					            ESP_LOGE(TAG, "Failed to synchronise device!");
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
        else
 | 
					            // Safely turn off all relays after a given number of failures
 | 
				
			||||||
 | 
					            if (fails > 5)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
            ESP_LOGI(TAG, "Successfully synchronised device!");
 | 
					                ESP_LOGE(TAG, "Many failures, will stop all relays...");
 | 
				
			||||||
 | 
					                // TODO : turn off all relays
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        system_sleep(10);
 | 
					            // Restart the card after too much failures
 | 
				
			||||||
 | 
					            if (fails > 10)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ESP_LOGE(TAG, "Too many failures, will try to reboot in 3 secs...");
 | 
				
			||||||
 | 
					                system_sleep(3);
 | 
				
			||||||
 | 
					                reboot();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    system_sleep(120);
 | 
					            system_sleep(SYNC_TIME_INTERVAL);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO : apply sync
 | 
				
			||||||
 | 
					        sync_response_print(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sync_response_free(res);
 | 
				
			||||||
 | 
					        system_sleep(SYNC_TIME_INTERVAL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reboot();
 | 
					    reboot();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,16 +148,16 @@ int secure_api_enroll_device()
 | 
				
			|||||||
    free(csr);
 | 
					    free(csr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *body = cJSON_PrintUnformatted(obj);
 | 
					    char *body = cJSON_PrintUnformatted(obj);
 | 
				
			||||||
 | 
					    cJSON_Delete(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!body)
 | 
					    if (!body)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ESP_LOGE(TAG, "Failed to generate JSON body!");
 | 
					        ESP_LOGE(TAG, "Failed to generate JSON body!");
 | 
				
			||||||
        cJSON_Delete(obj);
 | 
					 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *res = process_secure_request("/devices_api/mgmt/enroll", body);
 | 
					    char *res = process_secure_request("/devices_api/mgmt/enroll", body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cJSON_Delete(obj);
 | 
					 | 
				
			||||||
    free(body);
 | 
					    free(body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (res == NULL)
 | 
					    if (res == NULL)
 | 
				
			||||||
@@ -195,7 +195,7 @@ char *secure_api_get_dev_certificate()
 | 
				
			|||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *secure_api_sync_device()
 | 
					sync_response *secure_api_sync_device()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    cJSON *obj = cJSON_CreateObject();
 | 
					    cJSON *obj = cJSON_CreateObject();
 | 
				
			||||||
    if (!obj)
 | 
					    if (!obj)
 | 
				
			||||||
@@ -215,10 +215,53 @@ void *secure_api_sync_device()
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("JWT: %s\n", encoded_req);
 | 
					    // Prepare request body
 | 
				
			||||||
 | 
					    cJSON *json_body = cJSON_CreateObject();
 | 
				
			||||||
 | 
					    if (!json_body)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Failed to allocated memory to store sync request body!");
 | 
				
			||||||
        free(encoded_req);
 | 
					        free(encoded_req);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO : replace
 | 
					 | 
				
			||||||
    printf("here implement sync device logic\n");
 | 
					 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    cJSON_AddStringToObject(json_body, "payload", encoded_req);
 | 
				
			||||||
 | 
					    free(encoded_req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char *body = cJSON_PrintUnformatted(json_body);
 | 
				
			||||||
 | 
					    cJSON_Delete(json_body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!body)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Failed to allocated memory to store encoded sync request body!");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Send request
 | 
				
			||||||
 | 
					    char *res = process_secure_request("/devices_api/mgmt/sync", body);
 | 
				
			||||||
 | 
					    if (res == NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Sync request failed!");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Parse response
 | 
				
			||||||
 | 
					    cJSON *states = cJSON_Parse(res);
 | 
				
			||||||
 | 
					    free(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!states)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Failed to decode sync response from server!");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sync_response *sync_res = sync_response_parse(states);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cJSON_Delete(states);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!sync_res)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Failed to parse sync response from server!");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return sync_res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,6 +2,11 @@
 | 
				
			|||||||
 * Secure API functions
 | 
					 * Secure API functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sync_response.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
@@ -45,7 +50,7 @@ extern "C"
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * Returns NULL in case of failure
 | 
					     * Returns NULL in case of failure
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void *secure_api_sync_device();
 | 
					    sync_response *secure_api_sync_device();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										63
									
								
								esp32_device/main/sync_response.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								esp32_device/main/sync_response.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					#include "sync_response.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <esp_log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const static char *TAG = "sync_response";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sync_response *sync_response_parse(cJSON *res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    cJSON *relays_json = cJSON_GetObjectItem(res, "relays");
 | 
				
			||||||
 | 
					    if (relays_json == NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Missing relays status in sync response!");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int relays_size = cJSON_GetArraySize(relays_json);
 | 
				
			||||||
 | 
					    sync_response *sync_res = calloc(1, sizeof(sync_response) + relays_size * sizeof(bool));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!sync_res)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ESP_LOGE(TAG, "Failed to allocate memory to store synchronization response!");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sync_res->len = relays_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < sync_res->len; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sync_res->relays[i] = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cJSON *item = cJSON_GetArrayItem(relays_json, i);
 | 
				
			||||||
 | 
					        assert(item != NULL);
 | 
				
			||||||
 | 
					        cJSON *enabled = cJSON_GetObjectItem(item, "enabled");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (enabled == NULL)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ESP_LOGE(TAG, "At least a relay is missing the enabled field. Assuming false.");
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (cJSON_IsTrue(enabled))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sync_res->relays[i] = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return sync_res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sync_response_print(sync_response *res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ESP_LOGI(TAG, " === sync response begin === ");
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < res->len; i++)
 | 
				
			||||||
 | 
					        ESP_LOGI(TAG, "Relay[%d]=%s", i, res->relays[i] ? "ON" : "off");
 | 
				
			||||||
 | 
					    ESP_LOGI(TAG, " === sync response end === ");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sync_response_free(sync_response *res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (res != NULL)
 | 
				
			||||||
 | 
					        free(res);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								esp32_device/main/sync_response.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								esp32_device/main/sync_response.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Synchronisation response
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <cJSON.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C"
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    typedef struct sync_response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        size_t len;
 | 
				
			||||||
 | 
					        bool relays[];
 | 
				
			||||||
 | 
					    } sync_response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Decode synchronize response from server
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    sync_response *sync_response_parse(cJSON *res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Print synchronize reponse content
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void sync_response_print(sync_response *res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Free memory allocated for synchronize response
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void sync_response_free(sync_response *res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Reference in New Issue
	
	Block a user