Compare commits
9 Commits
b800b90337
...
5608b4e610
| Author | SHA1 | Date | |
|---|---|---|---|
| 5608b4e610 | |||
| b4220a3254 | |||
| 4d07d83904 | |||
| 274b7089d1 | |||
| e574bed96f | |||
| ce8427b0aa | |||
| 58abf4ec9b | |||
| 5704f2b57f | |||
| 51fc7cc710 |
@@ -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 }))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/sunny.svg" />
|
<link rel="icon" type="image/svg+xml" href="/assets/sunny.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>SolarEnergy</title>
|
<title>SolarEnergy</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
104
central_frontend/package-lock.json
generated
104
central_frontend/package-lock.json
generated
@@ -24,16 +24,16 @@
|
|||||||
"react-router-dom": "^6.26.2"
|
"react-router-dom": "^6.26.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.3.8",
|
"@types/react": "^18.3.10",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.6.0",
|
"@typescript-eslint/eslint-plugin": "^8.7.0",
|
||||||
"@typescript-eslint/parser": "^8.6.0",
|
"@typescript-eslint/parser": "^8.7.0",
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"eslint-plugin-react-refresh": "^0.4.12",
|
"eslint-plugin-react-refresh": "^0.4.12",
|
||||||
"typescript": "^5.6.2",
|
"typescript": "^5.6.2",
|
||||||
"vite": "^5.4.7"
|
"vite": "^5.4.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
@@ -2073,9 +2073,9 @@
|
|||||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.3.8",
|
"version": "18.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.10.tgz",
|
||||||
"integrity": "sha512-syBUrW3/XpnW4WJ41Pft+I+aPoDVbrBVQGEnbD7NijDGlVC+8gV/XKRY+7vMDlfPpbwYt0l1vd/Sj8bJGMbs9Q==",
|
"integrity": "sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
@@ -2101,17 +2101,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz",
|
||||||
"integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==",
|
"integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.6.0",
|
"@typescript-eslint/scope-manager": "8.7.0",
|
||||||
"@typescript-eslint/type-utils": "8.6.0",
|
"@typescript-eslint/type-utils": "8.7.0",
|
||||||
"@typescript-eslint/utils": "8.6.0",
|
"@typescript-eslint/utils": "8.7.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.6.0",
|
"@typescript-eslint/visitor-keys": "8.7.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@@ -2135,16 +2135,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz",
|
||||||
"integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==",
|
"integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.6.0",
|
"@typescript-eslint/scope-manager": "8.7.0",
|
||||||
"@typescript-eslint/types": "8.6.0",
|
"@typescript-eslint/types": "8.7.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.6.0",
|
"@typescript-eslint/typescript-estree": "8.7.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.6.0",
|
"@typescript-eslint/visitor-keys": "8.7.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2164,14 +2164,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz",
|
||||||
"integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==",
|
"integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.6.0",
|
"@typescript-eslint/types": "8.7.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.6.0"
|
"@typescript-eslint/visitor-keys": "8.7.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -2182,14 +2182,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz",
|
||||||
"integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==",
|
"integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.6.0",
|
"@typescript-eslint/typescript-estree": "8.7.0",
|
||||||
"@typescript-eslint/utils": "8.6.0",
|
"@typescript-eslint/utils": "8.7.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^1.3.0"
|
"ts-api-utils": "^1.3.0"
|
||||||
},
|
},
|
||||||
@@ -2207,9 +2207,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz",
|
||||||
"integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==",
|
"integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2221,14 +2221,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz",
|
||||||
"integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==",
|
"integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.6.0",
|
"@typescript-eslint/types": "8.7.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.6.0",
|
"@typescript-eslint/visitor-keys": "8.7.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@@ -2250,16 +2250,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz",
|
||||||
"integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==",
|
"integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "8.6.0",
|
"@typescript-eslint/scope-manager": "8.7.0",
|
||||||
"@typescript-eslint/types": "8.6.0",
|
"@typescript-eslint/types": "8.7.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.6.0"
|
"@typescript-eslint/typescript-estree": "8.7.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -2273,13 +2273,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz",
|
||||||
"integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==",
|
"integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.6.0",
|
"@typescript-eslint/types": "8.7.0",
|
||||||
"eslint-visitor-keys": "^3.4.3"
|
"eslint-visitor-keys": "^3.4.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4400,9 +4400,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.7",
|
"version": "5.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
|
||||||
"integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==",
|
"integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -26,15 +26,15 @@
|
|||||||
"react-router-dom": "^6.26.2"
|
"react-router-dom": "^6.26.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.3.8",
|
"@types/react": "^18.3.10",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.6.0",
|
"@typescript-eslint/eslint-plugin": "^8.7.0",
|
||||||
"@typescript-eslint/parser": "^8.6.0",
|
"@typescript-eslint/parser": "^8.7.0",
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"eslint-plugin-react-refresh": "^0.4.12",
|
"eslint-plugin-react-refresh": "^0.4.12",
|
||||||
"typescript": "^5.6.2",
|
"typescript": "^5.6.2",
|
||||||
"vite": "^5.4.7"
|
"vite": "^5.4.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 557 B After Width: | Height: | Size: 557 B |
@@ -62,7 +62,7 @@ export function LoginRoute() {
|
|||||||
<Grid
|
<Grid
|
||||||
size={{ sm: 4, md: 7, xs: false }}
|
size={{ sm: 4, md: 7, xs: false }}
|
||||||
sx={{
|
sx={{
|
||||||
backgroundImage: 'url("/sun.jpg")',
|
backgroundImage: 'url("/assets/sun.jpg")',
|
||||||
backgroundColor: (t) =>
|
backgroundColor: (t) =>
|
||||||
t.palette.mode === "light"
|
t.palette.mode === "light"
|
||||||
? t.palette.grey[50]
|
? t.palette.grey[50]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { AsyncWidget } from "../widgets/AsyncWidget";
|
|||||||
import { BoolText } from "../widgets/BoolText";
|
import { BoolText } from "../widgets/BoolText";
|
||||||
import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer";
|
import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer";
|
||||||
import { TimeWidget } from "../widgets/TimeWidget";
|
import { TimeWidget } from "../widgets/TimeWidget";
|
||||||
import { EditDeviceRelaysDialog } from "../dialogs/EditDeviceRelaysDialog";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
export function RelaysListRoute(p: {
|
export function RelaysListRoute(p: {
|
||||||
|
|||||||
6
esp32_device/.vscode/settings.json
vendored
6
esp32_device/.vscode/settings.json
vendored
@@ -49,6 +49,10 @@
|
|||||||
"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",
|
||||||
|
"gpio.h": "c",
|
||||||
|
"esp_system.h": "c",
|
||||||
|
"relays.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
esp32_device/docs/pinout.fzz
Normal file
BIN
esp32_device/docs/pinout.fzz
Normal file
Binary file not shown.
@@ -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 "relays.c" "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 ".")
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,6 @@
|
|||||||
*/
|
*/
|
||||||
#define DEV_VERSION "0.0.1"
|
#define DEV_VERSION "0.0.1"
|
||||||
|
|
||||||
/**
|
|
||||||
* Device max number of relays
|
|
||||||
*/
|
|
||||||
#define DEV_MAX_RELAYS 1
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backend unsecure API URL
|
* Backend unsecure API URL
|
||||||
*/
|
*/
|
||||||
@@ -44,3 +39,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
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "secure_api.h"
|
#include "secure_api.h"
|
||||||
#include "ethernet.h"
|
#include "ethernet.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "relays.h"
|
||||||
|
|
||||||
static const char *TAG = "main";
|
static const char *TAG = "main";
|
||||||
|
|
||||||
@@ -21,6 +22,10 @@ void app_main(void)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "SolarEnergy WT32-ETH01 device");
|
ESP_LOGI(TAG, "SolarEnergy WT32-ETH01 device");
|
||||||
|
|
||||||
|
// Turn off all relays
|
||||||
|
relays_turn_off_all();
|
||||||
|
relays_setup();
|
||||||
|
|
||||||
// Initialize storage
|
// Initialize storage
|
||||||
if (storage_init() == false)
|
if (storage_init() == false)
|
||||||
{
|
{
|
||||||
@@ -167,22 +172,46 @@ 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)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Failed to synchronise device!");
|
fails += 1;
|
||||||
}
|
ESP_LOGE(TAG, "Failed to synchronise device! (number=%d)", fails);
|
||||||
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...");
|
||||||
|
relays_turn_off_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fails = 0;
|
||||||
|
|
||||||
|
sync_response_print(res);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < relays_count(); i++)
|
||||||
|
{
|
||||||
|
relays_set(i, sync_response_is_relay_on(res, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_response_free(res);
|
||||||
|
system_sleep(SYNC_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
reboot();
|
reboot();
|
||||||
}
|
}
|
||||||
|
|||||||
63
esp32_device/main/relays.c
Normal file
63
esp32_device/main/relays.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include <driver/gpio.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#include "relays.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
static const char *TAG = "relays";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device relays GPIO ids
|
||||||
|
*/
|
||||||
|
static int DEVICE_GPIO_IDS[3] = {4, 14, 15};
|
||||||
|
|
||||||
|
int relays_count()
|
||||||
|
{
|
||||||
|
return sizeof(DEVICE_GPIO_IDS) / sizeof(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relays_setup()
|
||||||
|
{
|
||||||
|
int pin_bit_mask = 0;
|
||||||
|
for (size_t i = 0; i < relays_count(); i++)
|
||||||
|
{
|
||||||
|
pin_bit_mask |= 1ULL << DEVICE_GPIO_IDS[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero-initialize the config structure.
|
||||||
|
gpio_config_t io_conf = {};
|
||||||
|
// disable interrupt
|
||||||
|
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
|
// set as output mode
|
||||||
|
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||||
|
// bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||||
|
io_conf.pin_bit_mask = pin_bit_mask;
|
||||||
|
// disable pull-down mode
|
||||||
|
io_conf.pull_down_en = 0;
|
||||||
|
// disable pull-up mode
|
||||||
|
io_conf.pull_up_en = 0;
|
||||||
|
// configure GPIO with the given settings
|
||||||
|
gpio_config(&io_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relays_turn_off_all()
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Turning off all relays...");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < relays_count(); i++)
|
||||||
|
{
|
||||||
|
relays_set(i, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void relays_set(int number, bool is_on)
|
||||||
|
{
|
||||||
|
size_t gpio_id = DEVICE_GPIO_IDS[number];
|
||||||
|
ESP_LOGI(TAG, "Set relay %d (gpio %d) to %s", number, gpio_id, is_on ? "on" : "off");
|
||||||
|
|
||||||
|
int res = gpio_set_level(gpio_id, is_on ? 0 : 1);
|
||||||
|
if (res != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to toggle GPIO %d : %d", gpio_id, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
esp32_device/main/relays.h
Normal file
36
esp32_device/main/relays.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Relays management
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the max number of relays
|
||||||
|
*/
|
||||||
|
int relays_count();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the relays
|
||||||
|
*/
|
||||||
|
void relays_setup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn off all relays
|
||||||
|
*/
|
||||||
|
void relays_turn_off_all();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on / off a relay
|
||||||
|
*/
|
||||||
|
void relays_set(int number, bool is_on);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "http_client.h"
|
#include "http_client.h"
|
||||||
#include "jwt.h"
|
#include "jwt.h"
|
||||||
|
#include "relays.h"
|
||||||
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ static cJSON *genDevInfo()
|
|||||||
return NULL;
|
return NULL;
|
||||||
cJSON_AddStringToObject(json, "reference", DEV_REFERENCE);
|
cJSON_AddStringToObject(json, "reference", DEV_REFERENCE);
|
||||||
cJSON_AddStringToObject(json, "version", DEV_VERSION);
|
cJSON_AddStringToObject(json, "version", DEV_VERSION);
|
||||||
cJSON_AddNumberToObject(json, "max_relays", DEV_MAX_RELAYS);
|
cJSON_AddNumberToObject(json, "max_relays", relays_count());
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,16 +149,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 +196,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 +216,54 @@ 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);
|
||||||
|
free(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
|
||||||
}
|
}
|
||||||
|
|||||||
75
esp32_device/main/sync_response.c
Normal file
75
esp32_device/main/sync_response.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#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 === ");
|
||||||
|
ESP_LOGI(TAG, "# of relays: %d", res->len);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sync_response_is_relay_on(sync_response *res, int relay_number)
|
||||||
|
{
|
||||||
|
if (res->len <= relay_number)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Requested state of an unconfigured relay (%d). Defaulting to off.", relay_number);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res->relays[relay_number];
|
||||||
|
}
|
||||||
44
esp32_device/main/sync_response.h
Normal file
44
esp32_device/main/sync_response.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the desired status of a relay
|
||||||
|
*/
|
||||||
|
bool sync_response_is_relay_on(sync_response *res, int relay_number);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user