view rust/src/config.rs @ 599:f71cf1ad745f rust

updated toml serde works OK
author Matt Johnston <matt@ucc.asn.au>
date Tue, 07 Feb 2017 22:35:29 +0800
parents d4fbfb5c46ff
children 9c76f3cf01ea
line wrap: on
line source

extern crate toml;

use std::fs::File;
use std::io::Read;
use serde::{Serialize,Deserialize,Deserializer,Serializer};

#[derive(Deserialize,Serialize,Debug,Clone)]
#[allow(non_snake_case)]
pub struct Config {
    pub SENSOR_SLEEP: u64,
    pub UPLOAD_SLEEP: u64,

    pub FRIDGE_DELAY: u64,
    pub FRIDGE_WORT_INVALID_TIME: u64,

    pub MAX_READINGS: u32,

    pub PARAMS_FILE: String,

    pub SENSOR_BASE_DIR: String,
    pub FRIDGE_GPIO_PIN: u32,

    pub AMBIENT_NAME: String,
    pub FRIDGE_NAME: String,
    pub WORT_NAME: String,
    pub INTERNAL_TEMPERATURE: String,

    pub HMAC_KEY: String,
    pub SERVER_URL: String,
    pub UPDATE_URL: String, 
    pub SETTINGS_URL: String,
}

impl Config {

    pub fn default() -> Self {
        Config {
            SENSOR_SLEEP: 5,
            UPLOAD_SLEEP: 83,

            FRIDGE_DELAY: 600, // 10 mins, to avoid fridge damage from frequent cycling off/on
            FRIDGE_WORT_INVALID_TIME: 300, // 5 mins

            // 12 hours of "offline" readings stored
            MAX_READINGS: 12*60*60 / 15, // 15 is SENSOR_SLEEP

            //PARAMS_FILE: os.path.join(os.path.dirname(__file__), "tempserver.conf")
            PARAMS_FILE: "tempserver.conf".to_string(),

            SENSOR_BASE_DIR: "/sys/devices/w1_bus_master2".to_string(),
            FRIDGE_GPIO_PIN: 17,
            //WORT_NAME: "28-0000042cf4dd".to_string(),
            //FRIDGE_NAME: "28-0000042cccc4".to_string(),
            //AMBIENT_NAME: "28-0000042c6dbb".to_string(),
            AMBIENT_NAME: "missingambient".to_string(),
            FRIDGE_NAME: "28-0000042c6dbb".to_string(),
            WORT_NAME: "28-0000042cccc4".to_string(), // was fridge
            INTERNAL_TEMPERATURE: "/sys/class/thermal/thermal_zone0/temp".to_string(),

            HMAC_KEY: "a key".to_string(),
            SERVER_URL: "https://evil.ucc.asn.au/~matt/templog".to_string(),
            UPDATE_URL: "https://evil.ucc.asn.au/~matt/templog/update".to_string(),
            SETTINGS_URL: "https://evil.ucc.asn.au/~matt/templog/get_settings".to_string(),
        }
    }

    pub fn to_toml_string(&self) -> String {
        toml::to_string(self).unwrap()
    }


    pub fn merge(&self, conf: &str) -> Result<Self, String>{
        println!("config {}", conf);
        let mut new_toml = try!(toml::from_str(conf).map_err(|e| e.to_string()));
        let mut ex_val = toml::Value::try_from(self).unwrap();
        let mut ex_toml = ex_val.as_table_mut().unwrap();
        ex_toml.append(&mut new_toml);
        let ret: Self = toml::Value::Table(ex_toml.clone()).try_into().unwrap();
        return Ok(ret)


        /*
        let mut p = toml::Parser::new(&conf);
        let p =
        p.parse()
            .ok_or_else(|| {
                format!("toml parsing failed: {:?}", p.errors)
            })
            .map(|mut new_toml| {
                let mut e = toml::Encoder::new();
                self.serialize(&mut e).unwrap(); // XXX what could go wrong?
                let mut ex_toml = e.toml;
                ex_toml.append(&mut new_toml);
                let mut dec = toml::Decoder::new(toml::Value::Table(ex_toml));
                Self::deserialize(&mut dec).unwrap() // could this go wrong?
            })
            */
    }

    pub fn merge_file(&self, filename: &str) -> Result<Self, String>{

        let r = File::open(filename)
            .map_err(|e| e.to_string())
            .and_then(|mut f| {
                let mut s = String::new();
                f.read_to_string(&mut s)
                    .map_err(|e| e.to_string())
                    .map(|_| s)
            });

        r.and_then(|s| {
            self.merge(&s)
        })
        .map_err(|e| {
            format!("Error loading config file {}: {}",
                    filename, e)
        })
    }
}