feat: add service and hotspot

This commit is contained in:
itsscb 2024-10-28 22:32:54 +01:00
parent e67675553f
commit cf4c4c7a65
4 changed files with 113 additions and 102 deletions

View File

@ -10,6 +10,7 @@ pub enum Card {
Next,
Previous,
Shuffle,
ToggleHotspot,
}
impl From<&Card> for Option<Card> {

View File

@ -1,3 +1,6 @@
pub mod card;
pub mod card_reader;
pub mod error;
pub mod library;
pub mod portal;
pub mod service;

View File

@ -1,111 +1,27 @@
use marlinbox_rs::{card::Card, library::Library};
use rodio::{Decoder, OutputStream, Sink};
use rusb::{Context, DeviceHandle, UsbContext};
use std::{fs::File, io::BufReader, time::Duration};
use std::{
fs::File,
sync::{Arc, Mutex},
};
const VID: u16 = 0xffff; // Replace with your device's Vendor ID
const PID: u16 = 0x0035; // Replace with your device's Product ID
use marlinbox_rs::{card_reader, library::Library, service};
fn extract_card_id(buf: &[u8]) -> Option<String> {
let significant_indices = [2, 18, 34, 50, 66, 82, 98, 114];
let extracted: Vec<u8> = significant_indices
.iter()
.filter_map(|&i| buf.get(i).copied())
.collect();
if extracted.len() == 8 && extracted.iter().all(|&b| b != 0) {
Some(extracted.iter().fold(String::new(), |mut acc, &b| {
acc.push_str(&format!("{b:02X}"));
acc
}))
} else {
None
}
}
const VID: u16 = 0xffff;
const PID: u16 = 0x0035;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let music: Arc<Mutex<Library>> = Arc::new(Mutex::new(serde_json::from_reader(File::open(
"music.json",
)?)?));
let sink = Sink::try_new(&stream_handle).unwrap();
let (tx, rx) = crossbeam_channel::bounded(10);
let music: Library = serde_json::from_reader(File::open("music.json")?)?;
// let mut music = Library::new();
// music.update(
// "27271E24211E1E26",
// Some(Card::Play("02 - Disturbed - Immortalized.mp3".into())),
// );
// music.update(
// "27271E242121221F",
// Some(Card::Play(
// "11 - Disturbed - The Sound Of Silence.mp3".into(),
// )),
// );
// music.update("27271E2420222321", Card::Shuffle.into());
let mut handles = vec![];
let reader_handle = std::thread::spawn(move || card_reader::read(VID, PID, &tx));
handles.push(reader_handle);
service::run(&rx, &music)?;
// let music_json = serde_json::to_string_pretty(&music)?;
// fs::write("music.json", music_json)?;
let context = Context::new()?;
let handle: DeviceHandle<Context> = context
.open_device_with_vid_pid(VID, PID)
.ok_or("Device not found")?;
#[cfg(target_os = "linux")]
{
if handle.kernel_driver_active(0)? {
handle.detach_kernel_driver(0)?;
}
}
handle.claim_interface(0)?;
println!("Starting to read RFID cards...");
let mut buf = [0u8; 120];
// let mut last_id: Option<String> = None;
loop {
match handle.read_interrupt(0x81, &mut buf, Duration::from_millis(1000)) {
Ok(len) => {
if len == 120 {
if let Some(card_id) = extract_card_id(&buf) {
// if last_id.as_ref() != Some(&card_id) {
println!("Card ID: {card_id}");
if let Some(music_file) = music.get(card_id.as_ref()) {
println!("Playing: {music_file:?}");
match music_file {
Card::Play(music_file) => {
sink.stop();
let file =
BufReader::new(File::open(music_file.as_ref()).unwrap());
let source = Decoder::new(file).unwrap();
sink.append(source);
}
Card::Pause => sink.pause(),
Card::Resume => sink.play(),
Card::Next | Card::Previous => sink.stop(),
Card::Shuffle => {
if let Some(Card::Play(music_file)) = music.get_random() {
sink.stop();
let file = BufReader::new(
File::open(music_file.as_ref()).unwrap(),
);
let source = Decoder::new(file).unwrap();
sink.append(source);
}
}
}
} else {
println!("No music file found for this card");
}
}
}
}
Err(rusb::Error::Timeout) => {
// last_id = None;
}
Err(e) => eprintln!("Error: {e:?}"),
}
for handle in handles {
let _ = handle.join().unwrap();
}
Ok(())
}

91
src/service.rs Normal file
View File

@ -0,0 +1,91 @@
use std::{
fs::File,
io::BufReader,
sync::{Arc, Mutex},
};
use crossbeam_channel::Receiver;
use rodio::{Decoder, OutputStream, Sink};
use wifi_rs::{prelude::*, WiFi};
use crate::{card::Card, error::Error, library::Library};
fn toggle_hotspot(enable: bool) -> Result<(), Error> {
let config = Config {
interface: Some("wlp59s0"),
};
let mut hotspot = WiFi::new(Some(config));
if enable {
hotspot.create_hotspot("MARLIN", "M4rl!nB0x", None)?;
} else {
hotspot.stop_hotspot()?;
}
Ok(())
}
/// Runs the service.
///
/// # Arguments
///
/// * `rx` - The receiver channel.
/// * `library` - The library.
///
/// # Errors
///
/// Returns an error if there is an issue running the service.
pub fn run(rx: &Receiver<Arc<str>>, library: &Arc<Mutex<Library>>) -> Result<(), Error> {
let (_stream, stream_handle) = OutputStream::try_default().map_err(Error::from)?;
let sink = Sink::try_new(&stream_handle)?;
let mut hotspot_enabled = false;
loop {
match rx.recv() {
Ok(card_id) => {
println!("Card ID: {card_id}");
let library_lock = library.lock()?;
let card = library_lock.get(&card_id);
if let Some(music_file) = card {
println!("Playing: {music_file:?}");
match music_file {
Card::Play(music_file) => {
sink.stop();
let file = BufReader::new(File::open(music_file.as_ref())?);
let source = Decoder::new(file)?;
sink.append(source);
}
Card::Pause => sink.pause(),
Card::Resume => sink.play(),
Card::Next | Card::Previous => sink.stop(),
Card::Shuffle => {
let card = library_lock.get_random();
if let Some(Card::Play(music_file)) = card {
sink.stop();
let file = BufReader::new(File::open(music_file.as_ref())?);
let source = Decoder::new(file)?;
sink.append(source);
}
}
Card::ToggleHotspot => {
toggle_hotspot(!hotspot_enabled)?;
hotspot_enabled = !hotspot_enabled;
}
}
} else {
println!("No music file found for this card");
}
drop(library_lock);
}
Err(e) => match e {
crossbeam_channel::RecvError => break,
},
}
}
Ok(())
}