Skip to content

Instantly share code, notes, and snippets.

@cransom
Created November 13, 2022 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cransom/ff99cfc4ee4f63b9899074a2a41550b7 to your computer and use it in GitHub Desktop.
Save cransom/ff99cfc4ee4f63b9899074a2a41550b7 to your computer and use it in GitHub Desktop.
[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"] }
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