Ingen beskrivning
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tsdb.rs 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //! Interface to fill/query a timeseries database (InfluxDB).
  2. use chrono::{DateTime, Utc};
  3. use influxdb::InfluxDbWriteable;
  4. use influxdb::{Client, Timestamp};
  5. use log::error;
  6. use super::config::InfluxDbConfig;
  7. use protocol::{Location, Value};
  8. // TODO: Configuration mechanism.
  9. /// Interface to InfluxDB.
  10. pub struct TimeSeriesDatabase {
  11. client: Client,
  12. // TODO
  13. }
  14. impl TimeSeriesDatabase {
  15. /// Initializes the connection to InfluxDB.
  16. ///
  17. /// The function does not return an error. Instead, the code will automatically retry
  18. /// connection in case the connection cannot be established or the server closes the
  19. /// connection.
  20. pub fn init(config: &InfluxDbConfig) -> TimeSeriesDatabase {
  21. // TODO: Configurable address
  22. let client = Client::new(&config.address, "weather");
  23. let client = if config.user != "" && config.password != "" {
  24. client.with_auth(&config.user, &config.password)
  25. } else {
  26. client
  27. };
  28. // TODO: Ping the server.
  29. TimeSeriesDatabase { client }
  30. }
  31. /// Inserts values into the database.
  32. ///
  33. /// If there is no current connection to InfluxDB and the connection cannot be reestablished
  34. /// before the application is stopped, the values are lost. If multiple calls to this function
  35. /// occur while there is no current connection to InfluxDB, the values are queued and all
  36. /// values are inserted at a later time.
  37. ///
  38. /// # Arguments
  39. ///
  40. /// * `time` - time at which the values were received
  41. /// * `location` - location of the device which sent the values
  42. /// * `values` - list of values to be inserted into the database
  43. pub async fn insert(&mut self, time: DateTime<Utc>, location: Location, values: &[Value]) {
  44. let location = location.to_str();
  45. for value in values {
  46. if let Err(e) = self.try_insert(time, location.to_owned(), value).await {
  47. error!("Could not insert value into TSDB: {:?}", e);
  48. // TODO: Ping the server and do not try to write anything until ping succeds to
  49. // reduce debug spam.
  50. }
  51. }
  52. }
  53. async fn try_insert(
  54. &mut self,
  55. time: DateTime<Utc>,
  56. location: String,
  57. value: &Value,
  58. ) -> Result<(), TsdbError> {
  59. match *value {
  60. Value::Temperature(temperature) => {
  61. let temperature = temperature as f32 / value.decimal_factor() as f32;
  62. let reading = TemperatureReading {
  63. time: time,
  64. temperature,
  65. location,
  66. };
  67. self.client.query(&reading.into_query("weather")).await?;
  68. }
  69. Value::Pressure(pressure) => {
  70. let pressure = pressure as f32 / value.decimal_factor() as f32;
  71. let reading = PressureReading {
  72. time: time,
  73. pressure,
  74. location,
  75. };
  76. self.client.query(&reading.into_query("weather")).await?;
  77. }
  78. Value::Humidity(humidity) => {
  79. let humidity = humidity as f32 / value.decimal_factor() as f32;
  80. let reading = HumidityReading {
  81. time: time,
  82. humidity,
  83. location,
  84. };
  85. self.client.query(&reading.into_query("weather")).await?;
  86. }
  87. _ => {}
  88. }
  89. Ok(())
  90. }
  91. }
  92. #[derive(InfluxDbWriteable)]
  93. struct TemperatureReading {
  94. time: DateTime<Utc>,
  95. temperature: f32,
  96. #[influxdb(tag)]
  97. location: String,
  98. }
  99. #[derive(InfluxDbWriteable)]
  100. struct PressureReading {
  101. time: DateTime<Utc>,
  102. pressure: f32,
  103. #[influxdb(tag)]
  104. location: String,
  105. }
  106. #[derive(InfluxDbWriteable)]
  107. struct HumidityReading {
  108. time: DateTime<Utc>,
  109. humidity: f32,
  110. #[influxdb(tag)]
  111. location: String,
  112. }
  113. #[derive(thiserror::Error, Debug)]
  114. pub enum TsdbError {
  115. #[error("Database error")]
  116. Database(#[from] influxdb::Error),
  117. }