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": ""
},
"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": [
{
"type": "m3u",
"url": "https://example.com/list.m3u",
"cookies": null,
"rootCategory": null
"rootCategory": test
},
{
"type": "m3u-local",
@ -30,7 +57,7 @@
"tasks": [
{
"name": "crawler",
"interval": 60
"interval": 86400
},
{
"name": "processService",

View file

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

View file

@ -120,7 +120,7 @@ public class MPV implements TaskProcess {
@Override
public boolean spawn() throws IOException {
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);
@ -130,7 +130,7 @@ public class MPV implements TaskProcess {
@Override
public boolean isAlive() {
return process.isAlive();
return process != null ? process.isAlive() : false;
}
@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 {
// public PiIR(PiIRConfig config) {
import com.fasterxml.jackson.core.JsonProcessingException;
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
// public boolean spawn() throws IOException {
// }
private final String exec;
private final int gpio;
private final HashMap<String, MenuAction> binds = new HashMap<>();
// @Override
// public boolean isAlive() {
// }
private Process process = null;
private InputStream input = null;
// @Override
// public void stop() {
// }
private class PiIRReader implements Runnable {
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);
}
}