feat: add service and hotspot
This commit is contained in:
parent
e67675553f
commit
cf4c4c7a65
@ -10,6 +10,7 @@ pub enum Card {
|
||||
Next,
|
||||
Previous,
|
||||
Shuffle,
|
||||
ToggleHotspot,
|
||||
}
|
||||
|
||||
impl From<&Card> for Option<Card> {
|
||||
|
@ -1,3 +1,6 @@
|
||||
pub mod card;
|
||||
pub mod card_reader;
|
||||
pub mod error;
|
||||
pub mod library;
|
||||
pub mod portal;
|
||||
pub mod service;
|
||||
|
120
src/main.rs
120
src/main.rs
@ -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
91
src/service.rs
Normal 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(())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user