Skip to content

Commit

Permalink
Compute pv_power as sum more generically
Browse files Browse the repository at this point in the history
This makes it work for both the pcap and modbus backends.
  • Loading branch information
bmerry committed Dec 1, 2024
1 parent cd13833 commit 6aa8e60
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 76 deletions.
35 changes: 32 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

use csv::StringRecord;
use serde::Deserialize;
use serde::{Deserialize, Deserializer};
use std::collections::HashMap;
use std::env;
use std::error::Error;
Expand All @@ -41,13 +41,26 @@ enum FieldType {

use FieldType::*;

fn split_str<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
Ok(s.split(' ')
.map(|x| x.to_owned())
.filter(|x| !x.is_empty())
.collect())
}

#[derive(Deserialize, Clone)]
struct Field {
field_type: FieldType,
group: String,
name: String,
id: String,
scale: Option<f64>,
#[serde(deserialize_with = "split_str")]
sum_of: Vec<String>,
}

struct Record {
Expand Down Expand Up @@ -88,7 +101,8 @@ where
W: Write,
{
writeln!(w, "&[")?;
for record in records.iter() {
let mut by_id: HashMap<&str, usize> = HashMap::new();
for (i, record) in records.iter().enumerate() {
let field = &record.field;
let default_scale = match field.field_type {
Charge | Power | StateOfCharge | Unitless => Some(1.0),
Expand All @@ -114,6 +128,15 @@ where
Unitless => "",
};
let scale = field.scale.or(default_scale).unwrap();
let sum_of: Vec<usize> = field
.sum_of
.iter()
.map(|id| {
*by_id
.get(id.as_str())
.unwrap_or_else(|| panic!("Prior field {id:?} not found"))
})
.collect();
writeln!(
w,
r#" crate::fields::Field {{
Expand All @@ -124,9 +147,15 @@ where
scale: {scale:?},
bias: {bias:?},
unit: {unit:?},
sum_of: &{:?},
}},"#,
field.field_type, field.group, field.name, field.id
field.field_type,
field.group,
field.name,
field.id,
sum_of.as_slice()
)?;
by_id.insert(field.id.as_str(), i);
}
write!(w, "]")?;
Ok(())
Expand Down
118 changes: 59 additions & 59 deletions fields.csv
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
field_type,group,name,id,scale,v292_offset,v292_offset2,v302_offset,v302_offset2,reg,reg2
Energy,Battery,Total charge,battery_charge_total,,70,72,78,80,72,73
Energy,Battery,Total discharge,battery_discharge_total,,74,76,82,84,74,75
Energy,Grid,Total import,grid_import_total,,82,86,90,94,78,80
Frequency,Grid,Frequency,grid_frequency,,84,,92,,79,
Energy,Grid,Total export,grid_export_total,,88,90,96,98,81,82
Energy,Load,Total consumption,load_consumption_total,,96,98,104,106,85,86
Temperature,Inverter,DC Temperature,inverter_temperature_dc,,106,,114,,90,
Temperature,Inverter,AC Temperature,inverter_temperature_ac,,108,,116,,91,
Energy,PV,Total production,pv_production_total,,118,120,126,128,96,97
Charge,Battery,Capacity,battery_capacity,,140,,148,,107,
Voltage,PV,Voltage 1,pv_voltage_1,0.1,144,,152,,109,
Current,PV,Current 1,pv_current_1,0.1,146,,154,,110,
Voltage,PV,Voltage 2,pv_voltage_2,0.1,148,,156,,111,
Current,PV,Current 2,pv_current_2,0.1,150,,158,,112,
Voltage,Grid,Voltage,grid_voltage,0.1,176,,184,,150,
Voltage,Load,Voltage,load_voltage,0.1,184,,192,,154,
Current,Grid,Current,grid_current,0.01,196,,204,,160,
Current,Load,Current,load_current,0.01,204,,212,,164,
Power,Grid,Power L1,grid_power_l1,,210,,218,,167,
Power,Grid,Power,grid_power,,214,,222,,169,
Power,Inverter,Power,inverter_power,,226,,234,,175,
Power,Load,Power,load_power,,232,,240,,178,
Temperature,Battery,Temperature,battery_temperature,,240,,248,,182,
Voltage,Battery,Voltage,battery_voltage,0.01,242,,250,,183,
StateOfCharge,Battery,SOC,battery_soc,,244,,252,,184,
Power,PV,Power 1,pv_power_1,,248,,256,,186,
Power,PV,Power 2,pv_power_2,,250,,258,,187,
Power,Battery,Power,battery_power,,256,,264,,190,
Current,Battery,Current,battery_current,0.01,258,,266,,191,
Frequency,Load,Frequency,load_frequency,,260,,268,,192,
Unitless,Grid,Connected,grid_connected,,264,,272,,194,
Voltage,BMS,Charge Voltage,bms_charge_voltage,0.01,276,,286,,,
Current,BMS,Charge Limit Current,bms_charge_limit_current,1,280,,290,,,
Current,BMS,Discharge Limit Current,bms_discharge_limit_current,1,282,,292,,,
Voltage,BMS,Voltage,bms_voltage,0.01,286,,296,,,
Current,BMS,Current,bms_current,1,288,,298,,,
Temperature,BMS,Temperature,bms_temperature,,290,,300,,,
Time,Inverter,Program Time 1,inverter_program_time_1,,,,,,250,
Time,Inverter,Program Time 2,inverter_program_time_2,,,,,,251,
Time,Inverter,Program Time 3,inverter_program_time_3,,,,,,252,
Time,Inverter,Program Time 4,inverter_program_time_4,,,,,,253,
Time,Inverter,Program Time 5,inverter_program_time_5,,,,,,254,
Time,Inverter,Program Time 6,inverter_program_time_6,,,,,,255,
Power,Inverter,Program Power 1,inverter_program_power_1,,,,,,256,
Power,Inverter,Program Power 2,inverter_program_power_2,,,,,,257,
Power,Inverter,Program Power 3,inverter_program_power_3,,,,,,258,
Power,Inverter,Program Power 4,inverter_program_power_4,,,,,,259,
Power,Inverter,Program Power 5,inverter_program_power_5,,,,,,260,
Power,Inverter,Program Power 6,inverter_program_power_6,,,,,,261,
StateOfCharge,Inverter,Program SOC 1,inverter_program_soc_1,,,,,,268,
StateOfCharge,Inverter,Program SOC 2,inverter_program_soc_2,,,,,,269,
StateOfCharge,Inverter,Program SOC 3,inverter_program_soc_3,,,,,,270,
StateOfCharge,Inverter,Program SOC 4,inverter_program_soc_4,,,,,,271,
StateOfCharge,Inverter,Program SOC 5,inverter_program_soc_5,,,,,,272,
StateOfCharge,Inverter,Program SOC 6,inverter_program_soc_6,,,,,,273,
Power,Inverter,Program Power,inverter_program_power,,,,,,-1,
StateOfCharge,Inverter,Program SOC,inverter_program_soc,,,,,,-1,
Power,PV,Power,pv_power,,-1,,-1,,-1,
field_type,group,name,id,scale,v292_offset,v292_offset2,v302_offset,v302_offset2,reg,reg2,sum_of
Energy,Battery,Total charge,battery_charge_total,,70,72,78,80,72,73,
Energy,Battery,Total discharge,battery_discharge_total,,74,76,82,84,74,75,
Energy,Grid,Total import,grid_import_total,,82,86,90,94,78,80,
Frequency,Grid,Frequency,grid_frequency,,84,,92,,79,,
Energy,Grid,Total export,grid_export_total,,88,90,96,98,81,82,
Energy,Load,Total consumption,load_consumption_total,,96,98,104,106,85,86,
Temperature,Inverter,DC Temperature,inverter_temperature_dc,,106,,114,,90,,
Temperature,Inverter,AC Temperature,inverter_temperature_ac,,108,,116,,91,,
Energy,PV,Total production,pv_production_total,,118,120,126,128,96,97,
Charge,Battery,Capacity,battery_capacity,,140,,148,,107,,
Voltage,PV,Voltage 1,pv_voltage_1,0.1,144,,152,,109,,
Current,PV,Current 1,pv_current_1,0.1,146,,154,,110,,
Voltage,PV,Voltage 2,pv_voltage_2,0.1,148,,156,,111,,
Current,PV,Current 2,pv_current_2,0.1,150,,158,,112,,
Voltage,Grid,Voltage,grid_voltage,0.1,176,,184,,150,,
Voltage,Load,Voltage,load_voltage,0.1,184,,192,,154,,
Current,Grid,Current,grid_current,0.01,196,,204,,160,,
Current,Load,Current,load_current,0.01,204,,212,,164,,
Power,Grid,Power L1,grid_power_l1,,210,,218,,167,,
Power,Grid,Power,grid_power,,214,,222,,169,,
Power,Inverter,Power,inverter_power,,226,,234,,175,,
Power,Load,Power,load_power,,232,,240,,178,,
Temperature,Battery,Temperature,battery_temperature,,240,,248,,182,,
Voltage,Battery,Voltage,battery_voltage,0.01,242,,250,,183,,
StateOfCharge,Battery,SOC,battery_soc,,244,,252,,184,,
Power,PV,Power 1,pv_power_1,,248,,256,,186,,
Power,PV,Power 2,pv_power_2,,250,,258,,187,,
Power,Battery,Power,battery_power,,256,,264,,190,,
Current,Battery,Current,battery_current,0.01,258,,266,,191,,
Frequency,Load,Frequency,load_frequency,,260,,268,,192,,
Unitless,Grid,Connected,grid_connected,,264,,272,,194,,
Voltage,BMS,Charge Voltage,bms_charge_voltage,0.01,276,,286,,,,
Current,BMS,Charge Limit Current,bms_charge_limit_current,1,280,,290,,,,
Current,BMS,Discharge Limit Current,bms_discharge_limit_current,1,282,,292,,,,
Voltage,BMS,Voltage,bms_voltage,0.01,286,,296,,,,
Current,BMS,Current,bms_current,1,288,,298,,,,
Temperature,BMS,Temperature,bms_temperature,,290,,300,,,,
Time,Inverter,Program Time 1,inverter_program_time_1,,,,,,250,,
Time,Inverter,Program Time 2,inverter_program_time_2,,,,,,251,,
Time,Inverter,Program Time 3,inverter_program_time_3,,,,,,252,,
Time,Inverter,Program Time 4,inverter_program_time_4,,,,,,253,,
Time,Inverter,Program Time 5,inverter_program_time_5,,,,,,254,,
Time,Inverter,Program Time 6,inverter_program_time_6,,,,,,255,,
Power,Inverter,Program Power 1,inverter_program_power_1,,,,,,256,,
Power,Inverter,Program Power 2,inverter_program_power_2,,,,,,257,,
Power,Inverter,Program Power 3,inverter_program_power_3,,,,,,258,,
Power,Inverter,Program Power 4,inverter_program_power_4,,,,,,259,,
Power,Inverter,Program Power 5,inverter_program_power_5,,,,,,260,,
Power,Inverter,Program Power 6,inverter_program_power_6,,,,,,261,,
StateOfCharge,Inverter,Program SOC 1,inverter_program_soc_1,,,,,,268,,
StateOfCharge,Inverter,Program SOC 2,inverter_program_soc_2,,,,,,269,,
StateOfCharge,Inverter,Program SOC 3,inverter_program_soc_3,,,,,,270,,
StateOfCharge,Inverter,Program SOC 4,inverter_program_soc_4,,,,,,271,,
StateOfCharge,Inverter,Program SOC 5,inverter_program_soc_5,,,,,,272,,
StateOfCharge,Inverter,Program SOC 6,inverter_program_soc_6,,,,,,273,,
Power,Inverter,Program Power,inverter_program_power,,,,,,-1,,
StateOfCharge,Inverter,Program SOC,inverter_program_soc,,,,,,-1,,
Power,PV,Power,pv_power,,-1,,-1,,-1,,pv_power_1 pv_power_2
6 changes: 6 additions & 0 deletions src/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub struct Field<'a> {
/// Amount to add to the value, after scaling
pub bias: f64,
pub unit: &'a str,
/// Indices of other fields to sum to get this field
pub sum_of: &'a [usize],
}

impl<'a> Field<'a> {
Expand All @@ -64,6 +66,10 @@ impl<'a> Field<'a> {
}
(raw as f64) * self.scale + self.bias
}

pub fn from_sum(&self, values: &[f64]) -> f64 {
self.sum_of.iter().map(|idx| values[*idx]).sum()
}
}

#[cfg(test)]
Expand Down
12 changes: 4 additions & 8 deletions src/modbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,15 @@ async fn read_values(ctx: &mut Context) -> Result<Vec<f64>, std::io::Error> {
let mut values = Vec::with_capacity(FIELDS.len());
let mut parts = [0u16; 2];
for (field, regs) in FIELDS.iter().zip(REGISTERS.iter()) {
let value;
if !regs.is_empty() {
let value = if !regs.is_empty() {
for (i, reg) in regs.iter().enumerate() {
// TODO: better error handling
parts[i] = ctx.read_holding_registers(*reg, 1).await?[0];
}
value = field.from_u16s(parts[..regs.len()].iter().cloned());
field.from_u16s(parts[..regs.len()].iter().cloned())
} else {
value = 0.0;
}
field.from_sum(&values)
};
values.push(value);
}
// Get the inverter time, since that'll determine which program is current
Expand All @@ -87,9 +86,6 @@ async fn read_values(ctx: &mut Context) -> Result<Vec<f64>, std::io::Error> {
values[field_idx::INVERTER_PROGRAM_POWER] = values[field_idx::INVERTER_PROGRAM_POWER_1 + prog];
values[field_idx::INVERTER_PROGRAM_SOC] = values[field_idx::INVERTER_PROGRAM_SOC_1 + prog];

// Other computed fields
values[field_idx::PV_POWER] = values[field_idx::PV_POWER_1] + values[field_idx::PV_POWER_2];

Ok(values)
}

Expand Down
16 changes: 10 additions & 6 deletions src/pcap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,16 @@ impl Codec {
);
let mut values = Vec::with_capacity(FIELDS.len());
for (&offsets, field) in field_table.offsets.iter().zip(field_table.fields.iter()) {
let parts = offsets.iter().cloned().map(|offset| {
let bytes = &sliced.payload[offset..offset + 2];
let bytes = <&[u8; 2]>::try_from(bytes).unwrap();
u16::from_be_bytes(*bytes)
});
let value = field.from_u16s(parts);
let value = if !offsets.is_empty() {
let parts = offsets.iter().cloned().map(|offset| {
let bytes = &sliced.payload[offset..offset + 2];
let bytes = <&[u8; 2]>::try_from(bytes).unwrap();
u16::from_be_bytes(*bytes)
});
field.from_u16s(parts)
} else {
field.from_sum(&values)
};
values.push(value);
}
/* unwrapping timestamp_nanos_opt is safe because the encoding
Expand Down

0 comments on commit 6aa8e60

Please sign in to comment.