implement PiIR integration

This commit is contained in:
mykola2312 2024-04-28 03:22:03 +03:00
parent 5767116a07
commit 113f287415
5 changed files with 185 additions and 33 deletions

View file

@ -13,12 +13,39 @@
"password": "" "password": ""
}, },
"piir": {
"exec": "/home/iptv/.local/bin/piir",
"gpio": 17,
"binds": [
{
"data": "45 03",
"menuAction": "up"
},
{
"data": "45 5E",
"menuAction": "down"
},
{
"data": "45 02",
"menuAction": "left"
},
{
"data": "45 40",
"menuAction": "right"
},
{
"data": "45 5F",
"menuAction": "open"
}
]
},
"sources": [ "sources": [
{ {
"type": "m3u", "type": "m3u",
"url": "https://example.com/list.m3u", "url": "https://example.com/list.m3u",
"cookies": null, "cookies": null,
"rootCategory": null "rootCategory": test
}, },
{ {
"type": "m3u-local", "type": "m3u-local",
@ -30,7 +57,7 @@
"tasks": [ "tasks": [
{ {
"name": "crawler", "name": "crawler",
"interval": 60 "interval": 86400
}, },
{ {
"name": "processService", "name": "processService",

View file

@ -2,10 +2,10 @@ package com.mykola2312.mptv;
import com.mykola2312.mptv.crawler.Crawler; import com.mykola2312.mptv.crawler.Crawler;
import com.mykola2312.mptv.db.DB; import com.mykola2312.mptv.db.DB;
import com.mykola2312.mptv.piir.PiIR;
import com.mykola2312.mptv.task.ProcessService; import com.mykola2312.mptv.task.ProcessService;
import com.mykola2312.mptv.task.TaskDispatcher; import com.mykola2312.mptv.task.TaskDispatcher;
import com.mykola2312.mptv.ui.MainFrame; import com.mykola2312.mptv.ui.MainFrame;
import com.mykola2312.mptv.ui.MenuAction;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.flywaydb.core.Flyway; import org.flywaydb.core.Flyway;
@ -18,6 +18,7 @@ public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class); private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static ProcessService processService = new ProcessService(); public static ProcessService processService = new ProcessService();
public static MainFrame frame;
public static void main(String[] args) { public static void main(String[] args) {
// parse command line // parse command line
@ -82,27 +83,28 @@ public class Main {
// task dispatcher // task dispatcher
TaskDispatcher dispatcher = new TaskDispatcher(); TaskDispatcher dispatcher = new TaskDispatcher();
dispatcher.updateTaskConfig(config.tasks); dispatcher.updateTaskConfig(config.tasks);
//dispatcher.registerTask(crawler); // TODO: enable dispatcher.registerTask(crawler);
dispatcher.registerTask(processService); dispatcher.registerTask(processService);
new Thread(dispatcher).start(); new Thread(dispatcher).start();
// initialize ui // initialize ui
MainFrame frame = new MainFrame(); frame = new MainFrame();
frame.create(config.frame); frame.create(config.frame);
logger.info("mptv started"); // start PiIR
PiIR piir = new PiIR(config.piir);
try {
piir.spawn();
// TODO: remove this mock thread test processService.registerProcess(piir);
new Thread(new Runnable() { } catch (IOException e) {
@Override() logger.error("failed to spawn piir. fatal. exiting", e);
public void run() { System.exit(1);
try { Thread.sleep(5000L); } catch (InterruptedException e) {} }
frame.action(MenuAction.ACTION_RIGHT); logger.info("mptv started");
}
}).start();
frame.loop(); frame.loop();
} }

View file

@ -120,7 +120,7 @@ public class MPV implements TaskProcess {
@Override @Override
public boolean spawn() throws IOException { public boolean spawn() throws IOException {
process = Runtime.getRuntime().exec(new String[] { process = Runtime.getRuntime().exec(new String[] {
"mpv", url, "--input-ipc-server=" + MPV_SOCKET_PATH "mpv", "--vo=gpu", "--ao=pulse", "--fullscreen", "--input-ipc-server=" + MPV_SOCKET_PATH, url
}); });
waitForConnection(MPV_SOCKET_PATH); waitForConnection(MPV_SOCKET_PATH);
@ -130,7 +130,7 @@ public class MPV implements TaskProcess {
@Override @Override
public boolean isAlive() { public boolean isAlive() {
return process.isAlive(); return process != null ? process.isAlive() : false;
} }
@Override @Override

View file

@ -1,24 +1,132 @@
// package com.mykola2312.mptv.piir; package com.mykola2312.mptv.piir;
// import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
// import com.mykola2312.mptv.task.TaskProcess; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// public class PiIR implements TaskProcess { import com.fasterxml.jackson.core.JsonProcessingException;
// public PiIR(PiIRConfig config) { import com.mykola2312.mptv.Main;
import com.mykola2312.mptv.task.TaskProcess;
import com.mykola2312.mptv.ui.MenuAction;
// } public class PiIR implements TaskProcess {
private static final Logger logger = LoggerFactory.getLogger(PiIR.class);
// @Override private final String exec;
// public boolean spawn() throws IOException { private final int gpio;
// } private final HashMap<String, MenuAction> binds = new HashMap<>();
// @Override private Process process = null;
// public boolean isAlive() { private InputStream input = null;
// }
// @Override private class PiIRReader implements Runnable {
// public void stop() { private final PiIR piir;
// } private final InputStream input;
public boolean running = true;
public PiIRReader(PiIR piir, InputStream input) {
this.piir = piir;
this.input = input;
}
private static final int BUFFER_SIZE = 512;
@Override
public void run() {
byte[] buf = new byte[BUFFER_SIZE];
try {
while (running && !Thread.currentThread().isInterrupted()) {
// reader loop
int len = input.read(buf, 0, buf.length);
if (len < 0) {
logger.warn("reading error. exiting");
running = false;
return;
}
String line = new String(
Arrays.copyOfRange(buf, 0, len),
StandardCharsets.UTF_8);
try {
PiIRDump dump = PiIRDump.deserialize(line);
piir.handleDump(dump);
} catch (JsonProcessingException e) {
logger.warn("failed to deserialize dump!", e);
}
}
} catch (IOException e) {
logger.error("failed to read. exiting piir reader", e);
}
}
}
private PiIRReader reader = null;
private Thread readerThread = null;
private static String formatBindKey(String preData, String data) {
return preData != null ? preData + " " + data : data;
}
public PiIR(PiIRConfig config) {
this.exec = config.exec;
this.gpio = config.gpio;
for (var bind : config.binds) {
binds.put(formatBindKey(bind.preData, bind.data), bind.menuAction);
}
}
@Override
public boolean spawn() throws IOException {
process = Runtime.getRuntime().exec(new String[] {
exec, "dump", "--gpio", String.valueOf(gpio)
});
input = process.getInputStream();
reader = new PiIRReader(this, input);
readerThread = new Thread(reader);
readerThread.start();
return isAlive();
}
@Override
public boolean isAlive() {
return process != null ? process.isAlive() : false;
}
@Override
public void stop() {
if (reader != null) reader.running = false;
if (readerThread != null) readerThread.interrupt();
if (input != null) {
try {
input.close();
} catch (IOException e) {
logger.warn("failed to close input", e);
}
}
if (process != null) process.destroyForcibly();
reader = null;
readerThread = null;
process = null;
}
// } public void handleDump(PiIRDump dump) {
String key = formatBindKey(dump.pre_data, dump.data);
MenuAction action = binds.get(key);
if (action != null) {
Main.frame.action(action);
} else {
logger.warn(String.format(
"unknown piir dump pre_data \"%s\" data \"%s\"",
dump.pre_data, dump.data));
}
}
}

View file

@ -0,0 +1,15 @@
package com.mykola2312.mptv.piir;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class PiIRDump {
public String pre_data;
public String data;
public static PiIRDump deserialize(String data) throws JsonProcessingException {
return new ObjectMapper()
.readerFor(PiIRDump.class)
.readValue(data);
}
}