ccs: abstraction for data storage
This commit is contained in:
parent
88144693a8
commit
ed82c3444e
4 changed files with 78 additions and 27 deletions
|
@ -1,3 +1,5 @@
|
|||
use crate::storage::ControllerData;
|
||||
|
||||
mod pl;
|
||||
mod tristar;
|
||||
|
||||
|
@ -5,7 +7,7 @@ pub struct Controller {
|
|||
name: String,
|
||||
interval: std::time::Duration,
|
||||
inner: ControllerInner,
|
||||
data: std::sync::Arc<tokio::sync::RwLock<Option<ControllerState>>>,
|
||||
data: std::sync::Arc<ControllerData>,
|
||||
voltage_rx: Option<tokio::sync::mpsc::UnboundedReceiver<VoltageCommand>>,
|
||||
voltage_tx: Option<MultiTx>,
|
||||
}
|
||||
|
@ -69,7 +71,7 @@ impl Controller {
|
|||
},
|
||||
};
|
||||
|
||||
let data = std::sync::Arc::new(tokio::sync::RwLock::new(None));
|
||||
let data = std::sync::Arc::new(ControllerData::new());
|
||||
|
||||
let (voltage_tx, voltage_rx) = if config.follow_primary {
|
||||
let (a, b) = tokio::sync::mpsc::unbounded_channel();
|
||||
|
@ -91,7 +93,7 @@ impl Controller {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn get_data_ptr(&self) -> std::sync::Arc<tokio::sync::RwLock<Option<ControllerState>>> {
|
||||
pub fn get_data_ptr(&self) -> std::sync::Arc<ControllerData> {
|
||||
self.data.clone()
|
||||
}
|
||||
|
||||
|
@ -114,7 +116,7 @@ impl Controller {
|
|||
}
|
||||
}
|
||||
|
||||
*self.data.write().await = Some(data);
|
||||
*self.data.write_state().await = Some(data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ enum Commands {
|
|||
mod controller;
|
||||
mod gauges;
|
||||
|
||||
mod storage;
|
||||
|
||||
mod web;
|
||||
|
||||
pub const CHARGE_CONTROLLER_LABEL: &str = "charge_controller";
|
||||
|
@ -92,7 +94,7 @@ async fn run() -> eyre::Result<()> {
|
|||
|
||||
async fn watch(args: Args) -> eyre::Result<()> {
|
||||
let _w = config::init_config(&args.config);
|
||||
let (map, follow_voltage_tx, mut controller_tasks) = {
|
||||
let (storage, follow_voltage_tx, mut controller_tasks) = {
|
||||
let config = config::access_config().await;
|
||||
if config
|
||||
.charge_controllers
|
||||
|
@ -138,12 +140,16 @@ async fn watch(args: Args) -> eyre::Result<()> {
|
|||
controller_tasks.push(run_loop(controller));
|
||||
}
|
||||
|
||||
(map, follow_voltage_tx, controller_tasks)
|
||||
(
|
||||
storage::AllControllers::new(map),
|
||||
follow_voltage_tx,
|
||||
controller_tasks,
|
||||
)
|
||||
};
|
||||
|
||||
let server = web::rocket(web::ServerState::new(
|
||||
&config::access_config().await.primary_charge_controller,
|
||||
map,
|
||||
storage,
|
||||
follow_voltage_tx,
|
||||
));
|
||||
let server_task = tokio::task::spawn(server.launch());
|
||||
|
|
47
charge-controller-supervisor/src/storage.rs
Normal file
47
charge-controller-supervisor/src/storage.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
pub struct AllControllers {
|
||||
map: std::collections::HashMap<String, std::sync::Arc<ControllerData>>,
|
||||
}
|
||||
|
||||
impl AllControllers {
|
||||
pub const fn new(
|
||||
map: std::collections::HashMap<String, std::sync::Arc<ControllerData>>,
|
||||
) -> Self {
|
||||
Self { map }
|
||||
}
|
||||
|
||||
pub fn controller_names(&self) -> impl Iterator<Item = &String> {
|
||||
self.map.keys()
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Option<&std::sync::Arc<ControllerData>> {
|
||||
self.map.get(name)
|
||||
}
|
||||
|
||||
pub fn all_data(&self) -> impl Iterator<Item = (&String, &std::sync::Arc<ControllerData>)> {
|
||||
self.map.iter()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ControllerData {
|
||||
state: tokio::sync::RwLock<Option<crate::controller::ControllerState>>,
|
||||
}
|
||||
|
||||
impl ControllerData {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
state: tokio::sync::RwLock::const_new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn write_state(
|
||||
&self,
|
||||
) -> tokio::sync::RwLockWriteGuard<Option<crate::controller::ControllerState>> {
|
||||
self.state.write().await
|
||||
}
|
||||
|
||||
pub async fn read_state(
|
||||
&self,
|
||||
) -> tokio::sync::RwLockReadGuard<Option<crate::controller::ControllerState>> {
|
||||
self.state.read().await
|
||||
}
|
||||
}
|
|
@ -1,29 +1,25 @@
|
|||
use rocket::{get, post, routes, serde::json::Json, State};
|
||||
|
||||
use crate::storage::AllControllers;
|
||||
|
||||
mod static_handler;
|
||||
|
||||
pub struct ServerState {
|
||||
primary_name: String,
|
||||
map: std::collections::HashMap<
|
||||
String,
|
||||
std::sync::Arc<tokio::sync::RwLock<Option<crate::controller::ControllerState>>>,
|
||||
>,
|
||||
data: AllControllers,
|
||||
tx_to_controllers: crate::controller::MultiTx,
|
||||
}
|
||||
|
||||
impl ServerState {
|
||||
pub fn new(
|
||||
primary_name: &impl ToString,
|
||||
map: std::collections::HashMap<
|
||||
String,
|
||||
std::sync::Arc<tokio::sync::RwLock<Option<crate::controller::ControllerState>>>,
|
||||
>,
|
||||
data: AllControllers,
|
||||
tx_to_controllers: crate::controller::MultiTx,
|
||||
) -> Self {
|
||||
let primary_name = primary_name.to_string();
|
||||
Self {
|
||||
primary_name,
|
||||
map,
|
||||
data,
|
||||
tx_to_controllers,
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +61,7 @@ pub fn rocket(state: ServerState) -> rocket::Rocket<rocket::Build> {
|
|||
|
||||
#[get("/interfaces")]
|
||||
fn interfaces(state: &State<ServerState>) -> Json<Vec<String>> {
|
||||
Json(state.map.keys().cloned().collect())
|
||||
Json(state.data.controller_names().cloned().collect())
|
||||
}
|
||||
|
||||
#[get("/interfaces/primary")]
|
||||
|
@ -73,10 +69,10 @@ async fn primary_interface(
|
|||
state: &State<ServerState>,
|
||||
) -> Result<Json<crate::controller::CommonData>, ServerError> {
|
||||
let s = state
|
||||
.map
|
||||
.data
|
||||
.get(&state.primary_name)
|
||||
.ok_or(ServerError::InvalidPrimaryName)?
|
||||
.read()
|
||||
.read_state()
|
||||
.await;
|
||||
|
||||
Ok(Json(s.as_ref().ok_or(ServerError::NoData)?.common()))
|
||||
|
@ -88,8 +84,8 @@ async fn all_interfaces(
|
|||
) -> Json<Vec<(String, crate::controller::CommonData)>> {
|
||||
let mut data = Vec::new();
|
||||
|
||||
for (k, v) in &state.map {
|
||||
let v = v.read().await;
|
||||
for (k, v) in state.data.all_data() {
|
||||
let v = v.read_state().await;
|
||||
if let Some(v) = v.as_ref() {
|
||||
data.push((k.clone(), v.common().clone()));
|
||||
}
|
||||
|
@ -104,8 +100,8 @@ async fn all_interfaces_full(
|
|||
) -> Json<Vec<(String, crate::controller::ControllerState)>> {
|
||||
let mut data = Vec::new();
|
||||
|
||||
for (k, v) in &state.map {
|
||||
let v = v.read().await;
|
||||
for (k, v) in state.data.all_data() {
|
||||
let v = v.read_state().await;
|
||||
if let Some(v) = v.as_ref() {
|
||||
data.push((k.clone(), v.clone()));
|
||||
}
|
||||
|
@ -120,10 +116,10 @@ async fn interface(
|
|||
state: &State<ServerState>,
|
||||
) -> Result<Json<crate::controller::CommonData>, ServerError> {
|
||||
let data = state
|
||||
.map
|
||||
.data
|
||||
.get(name)
|
||||
.ok_or(ServerError::NotFound)?
|
||||
.read()
|
||||
.read_state()
|
||||
.await;
|
||||
Ok(Json(data.as_ref().ok_or(ServerError::NoData)?.common()))
|
||||
}
|
||||
|
@ -134,10 +130,10 @@ async fn interface_full(
|
|||
state: &State<ServerState>,
|
||||
) -> Result<Json<crate::controller::ControllerState>, ServerError> {
|
||||
let data = state
|
||||
.map
|
||||
.data
|
||||
.get(name)
|
||||
.ok_or(ServerError::NotFound)?
|
||||
.read()
|
||||
.read_state()
|
||||
.await;
|
||||
Ok(Json(data.as_ref().ok_or(ServerError::NoData)?.clone()))
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue