use serde::Serialize;
use serde_json::{Number, Value};
use std::collections::HashSet;
#[derive(Debug, Serialize)]
pub struct Param {
name: String,
param_type: ParamTypes,
ui_type: ParamUi,
properties: HashSet<ParamProperty>,
#[serde(skip_serializing_if = "Option::is_none")]
bounds: Option<ParamBounds>,
#[serde(rename = "data_type")]
value: ParamValue,
}
#[derive(Debug, PartialEq, Eq, Hash, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum ParamProperty {
Read,
Write,
}
#[derive(Debug, Clone)]
pub enum ParamValue {
String(String),
Bool(bool),
Integer(i64),
Float(f64),
}
#[derive(Debug, Serialize)]
pub enum ParamTypes {
#[serde(rename = "esp.param.name")]
Name,
#[serde(rename = "esp.param.power")]
Power,
#[serde(rename = "esp.param.brightness")]
Brightness,
#[serde(rename = "esp.param.cct")]
CCT,
#[serde(rename = "esp.param.hue")]
Hue,
#[serde(rename = "esp.param.saturation")]
Saturation,
#[serde(rename = "esp.param.intensity")]
Intensity,
#[serde(rename = "esp.param.speed")]
Speed,
#[serde(rename = "esp.param.direction")]
Direction,
#[serde(rename = "esp.param.temperature")]
AmbientTemperature,
#[serde(rename = "esp.param.setpoint-temperature")]
TargetTemperature,
#[serde(rename = "esp.param.humidity")]
AmbientHumidity,
#[serde(rename = "esp.param.ota_url")]
OTAURL,
#[serde(rename = "esp.param.ota_status")]
OTAStatus,
#[serde(rename = "esp.param.ota_info")]
OTAInfo,
#[serde(rename = "esp.param.tz")]
Timezone,
#[serde(rename = "esp.param.tz_posix")]
TimezonePOSIX,
#[serde(rename = "esp.param.schedules")]
Schedules,
#[serde(rename = "esp.param.reboot")]
Reboot,
#[serde(rename = "esp.param.factory-reset")]
FactoryReset,
#[serde(rename = "esp.param.wifi-reset")]
WiFiReset,
#[serde(rename = "esp.param.toggle")]
ToggleController,
#[serde(rename = "esp.param.range")]
RangeController,
#[serde(rename = "esp.param.mode")]
ModeController,
#[serde(rename = "esp.param.lockstate")]
LockState,
#[serde(rename = "esp.param.blinds-position")]
BlindsPosition,
#[serde(rename = "esp.param.garage-position")]
GaragePosition,
#[serde(rename = "esp.param.light-mode")]
LightMode,
#[serde(rename = "esp.paran.ac-mode")]
ACMode,
#[serde(rename = "esp.param.media-activity-state")]
MediaState,
#[serde(rename = "esp.param.media-activity-control")]
MediaControl,
#[serde(rename = "esp.param.volume")]
Volume,
#[serde(rename = "esp.param.mute")]
Mute,
#[serde(rename = "esp.param.app-selector")]
AppSelector,
#[serde(rename = "esp.param.input-selector")]
InputSelector,
#[serde(rename = "esp.param.contact-detection-state")]
ContactDetectionState,
#[serde(rename = "esp.param.motion-detection-state")]
MotionDetectionState,
#[serde(rename = "esp.param.arm-state")]
ArmState,
#[serde(rename = "esp.param.fire-alarm")]
FireAlarmState,
#[serde(rename = "esp.param.water-alarm")]
WaterAlarmState,
#[serde(rename = "esp.param.carbon-monoxide-alarm")]
CODetectionState,
#[serde(rename = "esp.param.burglary-alarm")]
BurglaryAlarmState,
}
#[derive(Debug, Serialize)]
pub enum ParamUi {
#[serde(rename = "esp.ui.text")]
Text,
#[serde(rename = "esp.ui.toggle")]
ToggleSwitch,
#[serde(rename = "esp.ui.slider")]
Slider,
#[serde(rename = "esp.ui.hue-slider")]
HueSlider,
#[serde(rename = "esp.ui.hue-circle")]
HueCircle,
#[serde(rename = "esp.ui.push-btn-big")]
PushButton,
#[serde(rename = "esp.ui.dropdown")]
Dropdown,
#[serde(rename = "esp.ui.trigger")]
Trigger,
#[serde(rename = "esp.ui.hidden")]
Hidden,
}
#[derive(Debug, Serialize)]
struct ParamBounds {
min: i32,
max: i32,
step: i32,
}
impl Param {
pub fn new(
name: &str,
initial_state: ParamValue,
param_type: ParamTypes,
properties: HashSet<ParamProperty>,
ui_type: ParamUi,
) -> Param {
Param {
name: name.to_owned(),
value: initial_state,
param_type,
properties,
ui_type,
bounds: None,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn value(&self) -> &ParamValue {
&self.value
}
pub fn add_bounds(&mut self, min: i32, max: i32, step: i32) {
self.bounds = Some(ParamBounds { min, max, step })
}
pub fn new_power(name: &str, initial_value: bool) -> Self {
let mut param_properties = HashSet::new();
param_properties.insert(ParamProperty::Read);
param_properties.insert(ParamProperty::Write);
Self::new(
name,
ParamValue::Bool(initial_value),
ParamTypes::Power,
param_properties,
ParamUi::ToggleSwitch,
)
}
pub fn new_brightness(name: &str, initial_value: u32) -> Self {
let mut param_properties = HashSet::new();
param_properties.insert(ParamProperty::Read);
param_properties.insert(ParamProperty::Write);
let mut param = Self::new(
name,
ParamValue::Integer(initial_value as i64),
ParamTypes::Brightness,
param_properties,
ParamUi::Slider,
);
param.add_bounds(0, 100, 1);
param
}
pub fn new_hue(name: &str, initial_value: u32) -> Self {
let mut param_properties = HashSet::new();
param_properties.insert(ParamProperty::Read);
param_properties.insert(ParamProperty::Write);
let mut param = Self::new(
name,
ParamValue::Integer(initial_value as i64),
ParamTypes::Hue,
param_properties,
ParamUi::HueSlider,
);
param.add_bounds(0, 360, 1);
param
}
pub fn new_satuation(name: &str, initial_value: u32) -> Self {
let mut param_properties = HashSet::new();
param_properties.insert(ParamProperty::Read);
param_properties.insert(ParamProperty::Write);
let mut param = Self::new(
name,
ParamValue::Integer(initial_value as i64),
ParamTypes::Saturation,
param_properties,
ParamUi::Slider,
);
param.add_bounds(0, 100, 1);
param
}
}
impl Serialize for ParamValue {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(match self {
ParamValue::String(_) => "string",
ParamValue::Bool(_) => "bool",
ParamValue::Integer(_) => "int",
ParamValue::Float(_) => "float",
})
}
}
impl From<ParamValue> for Value {
fn from(value: ParamValue) -> Self {
match value {
ParamValue::String(v) => Self::String(v),
ParamValue::Bool(v) => Self::Bool(v),
ParamValue::Integer(v) => Self::Number(Number::from(v)),
ParamValue::Float(v) => Self::Number(Number::from_f64(v).unwrap()),
}
}
}