Created
November 13, 2022 18:02
-
-
Save cransom/ff99cfc4ee4f63b9899074a2a41550b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "promimport" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
csv = "1.1" | |
serde = { version = "1", features = ["derive"] } | |
postgres = "0.19.4" | |
serde_json = "1.0" | |
postgres-types = { version = "0.2.4", features = ["derive"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use postgres_types::{ToSql, FromSql}; | |
use postgres::{Client, NoTls}; | |
use std::error::Error; | |
use std::process; | |
//use serde::Deserialize; | |
#[derive(Debug, ToSql, FromSql)] | |
struct Record { | |
ts: f64, | |
sensor: String, | |
measurement: String, | |
metric: f64, | |
} | |
fn f2c(temp: f64) -> f64 { | |
(temp - 32.0) * 5.0/9.0 | |
} | |
fn adjust_temp(record: &Record) -> f64 { | |
if record.measurement == "°F" { | |
f2c(record.metric) | |
} else { | |
record.metric | |
} | |
} | |
fn report(record: &Record) { | |
println!("hass_sensor_temperature_celsius{{domain=\"{}\",entity=\"{}\"}} {} {}", "sensor", record.sensor, adjust_temp(record),record.ts); | |
} | |
fn dump() -> Result<(), Box<dyn Error>> { | |
let mut client = Client::connect("host=nr1.mad.hubns.net user=homeassistant dbname=homeassistant", NoTls)?; | |
println!("# HELP hass_sensor_temperature_celsius Sensor data measured in celsius\n# TYPE hass_sensor_temperature_celsius gauge"); | |
let batch_size: i64 = 10_000; | |
let mut batch_counter: i64 = 0; | |
loop { | |
let rows = client.query("select floor(extract(epoch from last_updated)),entity_id,attributes::json->>'unit_of_measurement',state from states where state is not null and entity_id like '%temp%' order by last_updated asc limit $1 offset $2", &[&batch_size, &batch_counter])?; | |
if rows.len() == 0 { break; } | |
for row in rows { | |
let sample = Record { | |
ts: row.get(0), | |
sensor: row.get(1), | |
measurement: { | |
let val = row.try_get(2); | |
match val { | |
Ok(n) => n, | |
Err(_) => "°C".to_string(), | |
} | |
}, | |
metric: { | |
let val: &str = row.get(3); | |
match val.parse::<f64>() { | |
Ok(n) => n, | |
Err(_) => continue, | |
} | |
} | |
}; | |
if sample.measurement == "°C" || sample.measurement == "°F" { | |
report(&sample); | |
}; | |
} | |
batch_counter = batch_size + batch_counter; | |
} | |
println!("# EOF"); | |
Ok(()) | |
} | |
fn main() { | |
if let Err(err) = dump() { | |
println!("error running dump: {}", err); | |
process::exit(1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment