use std::error::Error;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;
use crate::{
client::{DeviceBase, HlapiClient, HlapiClientError},
devices::Side,
};
#[derive(Debug, Clone)]
pub struct Redstone {
client: HlapiClient,
uuid: Uuid,
}
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum RedstoneError {
#[error("HLAPI client error: {0}")]
HlapiClientError(#[from] HlapiClientError),
#[error("Invalid signal strength given")]
SignalStrengthInvalid,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
pub struct RedstoneChangedEvent {
pub side: Side,
#[serde(rename = "value")]
pub strength: u8,
}
impl Redstone {
pub fn get_redstone_input(&self, side: Side) -> Result<u8, RedstoneError> {
Ok(self.call("getRedstoneInput", &[&side as _], &[])?.0)
}
pub fn get_redstone_output(&self, side: Side) -> Result<u8, RedstoneError> {
Ok(self.call("getRedstoneOutput", &[&side as _], &[])?.0)
}
pub fn set_redstone_output(&self, side: Side, strength: u8) -> Result<(), RedstoneError> {
if strength > 15 {
return Err(RedstoneError::SignalStrengthInvalid);
}
self.call::<()>("setRedstoneOutput", &[&side as _, &strength as _], &[])?;
Ok(())
}
}
impl DeviceBase for Redstone {
const TYPE: &'static str = "redstone";
type Event = RedstoneChangedEvent;
fn new(client: HlapiClient, uuid: Uuid) -> Result<Self, HlapiClientError> {
Ok(Self { client, uuid })
}
fn uuid_base(&self) -> Uuid {
self.uuid
}
fn client(&self) -> &HlapiClient {
&self.client
}
fn parse_event(
typ: &str,
data: &serde_json::Value,
) -> Result<Self::Event, Box<dyn Error + Send + Sync>> {
if typ != "redstoneChanged" {
return Err("invalid event type".into());
}
Ok(serde_json::from_value(data.clone())?)
}
}