Skip to content

Instantly share code, notes, and snippets.

@revmischa
Created September 30, 2024 05:30
Show Gist options
  • Save revmischa/270ddbfc59d00cbc63b0cd6a299d0602 to your computer and use it in GitHub Desktop.
Save revmischa/270ddbfc59d00cbc63b0cd6a299d0602 to your computer and use it in GitHub Desktop.
Rust GPIO controller for Hue bridge
use gpio_cdev::{Chip, LineRequestFlags};
use reqwest::blocking::Client;
use serde_json::json;
use std::thread::sleep;
use std::time::{Duration, Instant};
// Hue API base URL and credentials
const HUE_API_URL: &str = "http://192.168.0.243/api/c7Gjkq902f8j12g10AfgG39GBj8/lights/5/state";
// Function to send a request to the Hue API to change bulb color
fn send_hue_request(on: bool) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let color = if on {
json!({ "bri": 254, "hue": 0, "sat": 254, "on": true }) // Red when active
} else {
json!({ "bri": 254, "hue": 46920, "sat": 254, "on": true }) // Purple when inactive
};
let response = client
.put(HUE_API_URL)
.json(&color)
.send()?;
if response.status().is_success() {
println!("Successfully sent request to change light.");
} else {
eprintln!("Failed to change light: {}", response.status());
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Open the GPIO chip
let mut chip = Chip::new("/dev/gpiochip0")?;
// Request GPIO line 23 (corresponding to XGPIOA[23] aka GPIO16) as input
let input_line_handle = chip
.get_line(23)?
.request(LineRequestFlags::INPUT, 0, "read-input")?;
// LED output line: GPIO 15 (XGPIOA[15]) as output
let output_line_handle = chip
.get_line(15)?
.request(LineRequestFlags::OUTPUT, 0, "write-output")?;
println!("Listening for GPIO pin state changes...");
let mut last_state = input_line_handle.get_value()?;
let debounce_time = Duration::from_millis(50); // Adjust this if needed
let mut last_change = Instant::now(); // To debounce
loop {
// Read the current state of the GPIO pin
match input_line_handle.get_value() {
Ok(current_state) => {
// Check for state change with basic debouncing
if current_state != last_state && last_change.elapsed() > debounce_time {
last_change = Instant::now(); // Reset the debounce timer
if current_state == 1 {
println!("Switch is ON (sending red request)");
if let Err(e) = send_hue_request(true) {
eprintln!("Failed to send request: {:?}", e);
}
} else {
println!("Switch is OFF (sending purple request)");
if let Err(e) = send_hue_request(false) {
eprintln!("Failed to send request: {:?}", e);
}
}
// Update the last known state
last_state = current_state;
// Toggle the LED output line
output_line_handle.set_value(current_state)?;
}
}
Err(e) => {
eprintln!("Error reading GPIO value: {:?}", e);
}
}
// Sleep to avoid busy-waiting (this is also part of the debouncing mechanism)
sleep(Duration::from_millis(100));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment