v0.14.2
This commit is contained in:
@@ -27,7 +27,7 @@ async fn export_configuration(
|
||||
|
||||
fn validate_configuration_header(export: &ConfigurationExport) -> Result<(), AppError> {
|
||||
if export.format_version != 3 {
|
||||
return Err(AppError::BadRequest("unsupported configuration export version; version 3 is required by GREE Controller 0.14.1".into()));
|
||||
return Err(AppError::BadRequest("unsupported configuration export version; version 3 is required by GREE Controller 0.14.2".into()));
|
||||
}
|
||||
if export.settings.control_strategy != "setpoint" {
|
||||
return Err(AppError::BadRequest(
|
||||
|
||||
+5
-1
@@ -1107,7 +1107,9 @@ fn compile_flow(
|
||||
&& native_time_range
|
||||
&& preset_for_schedule != "auto"
|
||||
&& mode_for_schedule == "auto"
|
||||
&& flow_bool(&action_node.config, "power").is_none();
|
||||
&& flow_bool(&action_node.config, "power").is_none()
|
||||
&& flow_bool(&action_node.config, "swing_vertical").is_none()
|
||||
&& flow_bool(&action_node.config, "swing_horizontal").is_none();
|
||||
if schedule_only {
|
||||
let zone_id = flow_string(&action_node.config, "zone_id")
|
||||
.ok_or_else(|| AppError::BadRequest("thermostat block needs a zone".into()))?;
|
||||
@@ -1285,6 +1287,8 @@ fn compile_flow(
|
||||
}
|
||||
item.action.mode = Some(mode);
|
||||
}
|
||||
item.action.swing_vertical = flow_bool(&action_node.config, "swing_vertical");
|
||||
item.action.swing_horizontal = flow_bool(&action_node.config, "swing_horizontal");
|
||||
}
|
||||
"device_action" => {
|
||||
let id = flow_string(&action_node.config, "device_id")
|
||||
|
||||
+78
-1
@@ -20,12 +20,81 @@ struct SystemInfoResponse {
|
||||
gree_received_frames_by_device: std::collections::HashMap<String, u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
struct DeviceGroupEnergySnapshot {
|
||||
total_kwh: f64,
|
||||
timestamp: Option<chrono::DateTime<Utc>>,
|
||||
source: String,
|
||||
origin: String,
|
||||
}
|
||||
|
||||
fn device_group_energy_snapshot(
|
||||
state: &AppState,
|
||||
group: &DeviceGroup,
|
||||
devices: &[Device],
|
||||
) -> Result<Option<DeviceGroupEnergySnapshot>, AppError> {
|
||||
let selected_source = match group.energy_source {
|
||||
EnergySourcePreference::GreeCloud => Some("gree_cloud"),
|
||||
EnergySourcePreference::HomeAssistant => Some("home_assistant"),
|
||||
EnergySourcePreference::Auto if group.energy_device_id.is_some() => Some("gree_cloud"),
|
||||
EnergySourcePreference::Auto if group.ha_energy_entity_id.is_some() => Some("home_assistant"),
|
||||
EnergySourcePreference::Auto => None,
|
||||
};
|
||||
|
||||
match selected_source {
|
||||
Some("gree_cloud") => {
|
||||
let Some(device_id) = group.energy_device_id.as_deref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
if let Some(device) = devices.iter().find(|device| device.id == device_id) {
|
||||
if let Some(total_kwh) = device
|
||||
.total_energy_kwh
|
||||
.filter(|value| value.is_finite() && *value >= 0.0)
|
||||
{
|
||||
return Ok(Some(DeviceGroupEnergySnapshot {
|
||||
total_kwh,
|
||||
timestamp: device
|
||||
.last_cloud_sync
|
||||
.clone()
|
||||
.or_else(|| device.last_seen.clone()),
|
||||
source: "gree_cloud".into(),
|
||||
origin: "cloud".into(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
Ok(state
|
||||
.db
|
||||
.last_energy_reading(device_id, "gree_cloud")?
|
||||
.map(|reading| DeviceGroupEnergySnapshot {
|
||||
total_kwh: reading.normalized_meter_kwh,
|
||||
timestamp: Some(reading.timestamp),
|
||||
source: "gree_cloud".into(),
|
||||
origin: "database".into(),
|
||||
}))
|
||||
}
|
||||
Some("home_assistant") => {
|
||||
let storage_id = format!("group:{}", group.id);
|
||||
Ok(state
|
||||
.db
|
||||
.last_energy_reading(&storage_id, "home_assistant")?
|
||||
.map(|reading| DeviceGroupEnergySnapshot {
|
||||
total_kwh: reading.normalized_meter_kwh,
|
||||
timestamp: Some(reading.timestamp),
|
||||
source: "home_assistant".into(),
|
||||
origin: "database".into(),
|
||||
}))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
struct BootstrapResponse {
|
||||
devices: Vec<Device>,
|
||||
zones: Vec<Zone>,
|
||||
groups: Vec<ClimateGroup>,
|
||||
device_groups: Vec<DeviceGroup>,
|
||||
device_group_energy: std::collections::HashMap<String, DeviceGroupEnergySnapshot>,
|
||||
schedules: Vec<Schedule>,
|
||||
automations: Vec<Automation>,
|
||||
flows: Vec<Flow>,
|
||||
@@ -59,6 +128,13 @@ async fn build_bootstrap(state: &AppState) -> Result<BootstrapResponse, AppError
|
||||
(settings_snapshot(&settings), settings.house_mode.clone())
|
||||
};
|
||||
let devices = state.db.list_devices()?;
|
||||
let device_groups = state.db.list_device_groups()?;
|
||||
let mut device_group_energy = std::collections::HashMap::new();
|
||||
for group in &device_groups {
|
||||
if let Some(snapshot) = device_group_energy_snapshot(state, group, &devices)? {
|
||||
device_group_energy.insert(group.id.clone(), snapshot);
|
||||
}
|
||||
}
|
||||
let system = build_system_info(state, &devices);
|
||||
let control_plan = engine::get_control_plan_snapshot(state).await?;
|
||||
|
||||
@@ -66,7 +142,8 @@ async fn build_bootstrap(state: &AppState) -> Result<BootstrapResponse, AppError
|
||||
devices,
|
||||
zones: state.db.list_zones()?,
|
||||
groups: state.db.list_groups()?,
|
||||
device_groups: state.db.list_device_groups()?,
|
||||
device_groups,
|
||||
device_group_energy,
|
||||
schedules: state.db.list_schedules()?,
|
||||
automations: state.db.list_automations()?,
|
||||
flows: state.db.list_flows()?,
|
||||
|
||||
Reference in New Issue
Block a user