Parse sync response from server

This commit is contained in:
Pierre HUBERT 2024-09-28 16:35:05 +02:00
parent 5704f2b57f
commit 58abf4ec9b
10 changed files with 205 additions and 23 deletions

View File

@ -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 }))
} }

View File

@ -1,3 +1,3 @@
pub mod files_utils; pub mod files_utils;
pub mod math_utils; pub mod math_utils;
pub mod time_utils; pub mod time_utils;

View File

@ -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"
} }
} }

View File

@ -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 ".")

View File

@ -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

View File

@ -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();
} }

View File

@ -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);
return NULL;
}
cJSON_AddStringToObject(json_body, "payload", encoded_req);
free(encoded_req); free(encoded_req);
// TODO : replace char *body = cJSON_PrintUnformatted(json_body);
printf("here implement sync device logic\n"); cJSON_Delete(json_body);
if (!body)
{
ESP_LOGE(TAG, "Failed to allocated memory to store encoded sync request body!");
return NULL; 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;
} }

View File

@ -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
} }

View 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);
}

View 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