feat: testing code, switch to rppal gpio lib, get mqtt working in both directions

This commit is contained in:
janishutz committed 2026-08-25 10:10:03 +02:00
1 parent 0b0efb1a0d
commit cd0f894e73
8 files changed
+727 -32

No files matched your search

+2 -2
View File
@@ -4,7 +4,7 @@ use yaml_rust2::{Yaml, YamlLoader};
#[derive(Debug)]
pub struct Topic {
pub topic: String,
pub pin: u16,
pub pin: u8,
pub mode: PinMode,
pub off_timeout: u64,
}
@@ -69,7 +69,7 @@ pub fn load_config(path: &str) -> Result<Config, Box<dyn std::error::Error>> {
.get(&Yaml::String(String::from("pin")))
.expect(&format!("Invalid topic configuration found at index {}. A pin is required", i))
.as_i64()
.expect(&format!("Invalid topic configuration found at index {}. The pin should be a 16 bit integer (0-65535)", i)) as u16,
.expect(&format!("Invalid topic configuration found at index {}. The pin should be a 16 bit integer (0-65535)", i)) as u8,
off_timeout: topic
.get(&Yaml::String(String::from("pin")))
.unwrap_or(&Yaml::Integer(-1))
+20 -14
View File
@@ -1,19 +1,19 @@
use gpio::{GpioIn, GpioOut};
use rppal::gpio;
use rumqttc::Publish;
use std::{collections::HashMap, time::SystemTime};
use crate::conf::{PinMode, Topic};
pub struct InputPin {
pub gpio: gpio::sysfs::SysFsGpioInput,
pub id: u16,
pub gpio: gpio::InputPin,
pub id: u8,
pub topic: String,
}
pub struct OutputPin {
gpio: gpio::sysfs::SysFsGpioOutput,
gpio: gpio::OutputPin,
off_timeout: u64,
pub id: u16,
pub id: u8,
pub topic: String,
}
@@ -23,8 +23,8 @@ pub struct OutputPin {
pub fn split_topics_and_configure_pins(topics: Vec<Topic>) -> (Vec<InputPin>, Vec<OutputPin>) {
let mut in_pins: Vec<InputPin> = Vec::new();
let mut out_pins: Vec<OutputPin> = Vec::new();
let mut in_used: Vec<u16> = Vec::new();
let mut out_used: Vec<u16> = Vec::new();
let mut in_used: Vec<u8> = Vec::new();
let mut out_used: Vec<u8> = Vec::new();
for topic in topics {
if topic.mode == PinMode::IN {
if in_used.contains(&topic.pin) {
@@ -36,10 +36,13 @@ pub fn split_topics_and_configure_pins(topics: Vec<Topic>) -> (Vec<InputPin>, Ve
} else if out_used.contains(&topic.pin) {
panic!("Pin {} used for both input and output!", topic.pin)
}
let pin = gpio::Gpio::new().expect("GPIO pin access failed");
in_pins.push(InputPin {
topic: topic.topic,
gpio: gpio::sysfs::SysFsGpioInput::open(topic.pin)
.expect(&format!("Unable to find GPIO pin {}", topic.pin)),
gpio: pin
.get(topic.pin)
.expect(&format!("Unable to find GPIO pin {}", topic.pin))
.into_input(),
id: topic.pin,
});
in_used.push(topic.pin)
@@ -53,10 +56,13 @@ pub fn split_topics_and_configure_pins(topics: Vec<Topic>) -> (Vec<InputPin>, Ve
} else if in_used.contains(&topic.pin) {
panic!("Pin {} used for both input and output!", topic.pin)
}
let pin = gpio::Gpio::new().expect("GPIO pin access failed");
out_pins.push(OutputPin {
topic: topic.topic,
gpio: gpio::sysfs::SysFsGpioOutput::open(topic.pin)
.expect(&format!("Unable to find GPIO pin {}", topic.pin)),
gpio: pin
.get(topic.pin)
.expect(&format!("Unable to find GPIO pin {}", topic.pin))
.into_output_low(),
id: topic.pin,
off_timeout: topic.off_timeout,
});
@@ -67,8 +73,9 @@ pub fn split_topics_and_configure_pins(topics: Vec<Topic>) -> (Vec<InputPin>, Ve
return (in_pins, out_pins);
}
pub fn read_pin(pin: &mut gpio::sysfs::SysFsGpioInput) -> u8 {
if let gpio::GpioValue::Low = pin.read_value().expect("Failed reading value") {
pub fn read_pin(pin: &mut gpio::InputPin) -> u8 {
// TODO: Consider moving to interrupt based solution
if let gpio::Level::High = pin.read() {
return 1;
} else {
return 0;
@@ -114,7 +121,6 @@ impl GPIOController {
.expect("Failed to retrieve pin")
.gpio
.set_low()
.unwrap_or_default();
}
}
}
+18 -8
View File
@@ -30,17 +30,27 @@ pub fn handler(config: Config) {
// Spawn thread to monitor pins
thread::spawn(move || {
let mut pin_state: Vec<u8> = vec![0; input_pins.len()];
let off: Vec<u8> = b"OFF".to_vec();
let on: Vec<u8> = b"ON".to_vec();
loop {
let mut i = 0;
for topic in input_pins.iter_mut() {
// TODO: handle fails
client
.publish(
String::from(&topic.topic) + &format!("/{}", topic.id),
QoS::AtLeastOnce,
false,
vec![read_pin(&mut topic.gpio)],
)
.unwrap_or_default();
let val = read_pin(&mut topic.gpio);
if val != pin_state[i] {
println!("Value change for pin {} detected", topic.id);
pin_state[i] = val;
client
.publish(
String::from(&topic.topic) + &format!("/{}", topic.id),
QoS::AtLeastOnce,
false,
if val == 0 { off.clone() } else { on.clone() },
)
.unwrap_or_default();
}
i += 1;
}
thread::sleep(Duration::from_millis(config.poll_interval));
}