feat: add service and hotspot
This commit is contained in:
parent
e67675553f
commit
cf4c4c7a65
@ -10,6 +10,7 @@ pub enum Card {
|
|||||||
Next,
|
Next,
|
||||||
Previous,
|
Previous,
|
||||||
Shuffle,
|
Shuffle,
|
||||||
|
ToggleHotspot,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Card> for Option<Card> {
|
impl From<&Card> for Option<Card> {
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
pub mod card;
|
pub mod card;
|
||||||
|
pub mod card_reader;
|
||||||
|
pub mod error;
|
||||||
pub mod library;
|
pub mod library;
|
||||||
pub mod portal;
|
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 std::{
|
||||||
use rodio::{Decoder, OutputStream, Sink};
|
fs::File,
|
||||||
use rusb::{Context, DeviceHandle, UsbContext};
|
sync::{Arc, Mutex},
|
||||||
use std::{fs::File, io::BufReader, time::Duration};
|
};
|
||||||
|
|
||||||
const VID: u16 = 0xffff; // Replace with your device's Vendor ID
|
use marlinbox_rs::{card_reader, library::Library, service};
|
||||||
const PID: u16 = 0x0035; // Replace with your device's Product ID
|
|
||||||
|
|
||||||
fn extract_card_id(buf: &[u8]) -> Option<String> {
|
const VID: u16 = 0xffff;
|
||||||
let significant_indices = [2, 18, 34, 50, 66, 82, 98, 114];
|
const PID: u16 = 0x0035;
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
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 handles = vec![];
|
||||||
// let mut music = Library::new();
|
let reader_handle = std::thread::spawn(move || card_reader::read(VID, PID, &tx));
|
||||||
// music.update(
|
handles.push(reader_handle);
|
||||||
// "27271E24211E1E26",
|
service::run(&rx, &music)?;
|
||||||
// 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 music_json = serde_json::to_string_pretty(&music)?;
|
for handle in handles {
|
||||||
// fs::write("music.json", music_json)?;
|
let _ = handle.join().unwrap();
|
||||||
|
|
||||||
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:?}"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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