51 lines
2.0 KiB
Rust
51 lines
2.0 KiB
Rust
impl Db {
|
|
pub fn add_ha_reading_if_due(&self, reading: &HaReading, min_interval_seconds: i64) -> Result<bool> {
|
|
let cutoff = reading.timestamp.clone() - Duration::seconds(min_interval_seconds.max(1));
|
|
let conn = self.lock()?;
|
|
let changed = conn.execute(
|
|
queries::INSERT_HA_READING_IF_DUE,
|
|
params![
|
|
reading.entity_id,
|
|
reading.zone_id,
|
|
reading.kind,
|
|
reading.timestamp.to_rfc3339(),
|
|
reading.temperature,
|
|
cutoff.to_rfc3339(),
|
|
],
|
|
)?;
|
|
Ok(changed > 0)
|
|
}
|
|
|
|
pub fn list_ha_history(&self, entity_id: Option<&str>, since: DateTime<Utc>, bucket_seconds: i64, limit: u32) -> Result<Vec<HaReading>> {
|
|
let conn = self.lock()?;
|
|
let bucket_seconds = bucket_seconds.max(1);
|
|
let limit = limit.clamp(1, 20_000) as i64;
|
|
let mut rows_out = Vec::new();
|
|
if let Some(entity_id) = entity_id {
|
|
let mut stmt = conn.prepare(queries::LIST_HA_HISTORY_BY_ENTITY_BUCKETED)?;
|
|
let rows = stmt.query_map(params![entity_id, since.to_rfc3339(), bucket_seconds, limit], Self::map_ha_reading)?;
|
|
for row in rows { rows_out.push(row?); }
|
|
} else {
|
|
let mut stmt = conn.prepare(queries::LIST_HA_HISTORY_ALL_BUCKETED)?;
|
|
let rows = stmt.query_map(params![since.to_rfc3339(), bucket_seconds, limit], Self::map_ha_reading)?;
|
|
for row in rows { rows_out.push(row?); }
|
|
}
|
|
Ok(rows_out)
|
|
}
|
|
|
|
fn map_ha_reading(row: &rusqlite::Row<'_>) -> rusqlite::Result<HaReading> {
|
|
let timestamp: String = row.get(4)?;
|
|
Ok(HaReading {
|
|
id: row.get(0)?,
|
|
entity_id: row.get(1)?,
|
|
zone_id: row.get(2)?,
|
|
kind: row.get(3)?,
|
|
timestamp: DateTime::parse_from_rfc3339(×tamp)
|
|
.map(|value| value.with_timezone(&Utc))
|
|
.unwrap_or_else(|_| Utc::now()),
|
|
temperature: row.get(5)?,
|
|
})
|
|
}
|
|
|
|
}
|