Snapshot of partial implementation (support for receiving, not yet for sending signals) of multiplexing/parsing/server driver for lirc, based on https://github.com/Boukefalos/mimis

This commit is contained in:
2015-06-11 23:03:40 +01:00
commit 75a5bf262e
32 changed files with 1943 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
package com.github.boukefalos.lirc;
import base.work.Listen;
public interface Lirc {
public void start();
public void register(Listen<Object> listen);
public void add(Object object);
// Required for Client / ClientListen to forward from separate Thread
public void input(Object object);
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc;
public class LircButton {
public String remote;
public String code;
public LircButton(String remote, String code) {
this.remote = remote;
this.code = code;
}
public lirc.Lirc.LircButton getProto() {
return lirc.Lirc.LircButton.newBuilder().setRemote(remote).setCode(code).build();
}
}

View File

@@ -0,0 +1,88 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import base.receiver.Receiver;
import base.server.channel.TcpClient;
import base.work.Listen;
public class LircClient extends TcpClient implements Receiver {
public static final int BUFFER_SIZE = 1024;
public static final String IP = "localhost";
public static final int PORT = 8765;
protected ArrayList<Listen<Object>> listenList;
protected String send;
public LircClient() {
super(IP, PORT, BUFFER_SIZE);
//send = Native.getValue(Registry.CURRENT_USER, "Software\\LIRC", "password");
listenList = new ArrayList<Listen<Object>>();
register(this);
}
public void register(Listen<Object> listen) {
listenList.add(listen);
}
public void remove(Listen<String[]> listen) {
listenList.remove(listen);
}
public void send(LircButton button) {
send(button, 0);
}
public void send(LircButton lircButton, int repeat) {
if (send == null) {
return;
}
String command = String.format("%s %s %s \n", send, lircButton.remote, lircButton.code);
try {
send(command.getBytes());
} catch (IOException e) {
logger.error("", e);
}
}
public void receive(byte[] buffer) {
receive(new String(buffer).trim());
}
protected void receive(String line) {
if (!line.startsWith("BEGIN")) {
Scanner scanner = new Scanner(line);
receive(scanner);
scanner.close();
}
}
protected void receive(Scanner scanner) {
scanner.next();
scanner.next();
String code = scanner.next();
String remote = scanner.next();
for (Listen<Object> lircbuttonListener : listenList) {
// Need to pass as String to assure consistent hash
lircbuttonListener.add(remote + " " + code);
}
}
}

View File

@@ -0,0 +1,97 @@
package com.github.boukefalos.lirc;
import java.io.IOException;
import java.util.Properties;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.Parameter;
import org.picocontainer.parameters.ConstantParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import base.work.Work;
import com.github.boukefalos.lirc.client.LircTcpClient;
import com.github.boukefalos.lirc.implementation.LocalImplementation;
import com.github.boukefalos.lirc.implementation.TcpImplementation;
import com.github.boukefalos.lirc.implementation.UdpImplementation;
import com.github.boukefalos.lirc.server.LircServer;
import com.github.boukefalos.lirc.server.LircTcpServer;
import com.github.boukefalos.lirc.server.LircUdpServer;
public class Loader {
protected static final String PROPERTIES_FILE = "Lirc.properties";
protected Logger logger = LoggerFactory.getLogger(Loader.class);
protected MutablePicoContainer pico;
public Loader(Properties properties) {
/* Initialise container */
pico = new DefaultPicoContainer();
/* Add implementation */
switch (properties.getProperty("implementation")) {
case "local":
pico.addComponent(LocalImplementation.class);
break;
case "remote":
//pico.addComponent(Remote.class);
break;
}
/* Add protocol */
if (properties.getProperty("protocol") != null) {
switch (properties.getProperty("protocol")) {
case "tcp":
pico.addComponent(TcpImplementation.class, TcpImplementation.class, new Parameter[]{
new ConstantParameter(properties.getProperty("remote.host")),
new ConstantParameter(Integer.valueOf(properties.getProperty("remote.port")))});
break;
case "udp":
pico.addComponent(UdpImplementation.class, UdpImplementation.class, new Parameter[] {
new ConstantParameter(properties.getProperty("remote.host")),
new ConstantParameter(Integer.valueOf(properties.getProperty("remote.port")))});
break;
}
}
/* Add server */
if (properties.getProperty("server") != null) {
switch (properties.getProperty("server.protocol")) {
case "tcp":
pico.addComponent(LircTcpServer.class, LircTcpServer.class, new Parameter[]{
new ConstantParameter(getLirc()),
new ConstantParameter(Integer.valueOf(properties.getProperty("server.port"))),
new ConstantParameter(LircTcpClient.class)});
break;
case "udp":
pico.addComponent(LircUdpServer.class, LircUdpServer.class, new Parameter[]{
new ConstantParameter(getLirc()),
new ConstantParameter(Integer.valueOf(properties.getProperty("server.port")))});
}
}
}
public static Loader getLoader() throws IOException {
return getLoader(PROPERTIES_FILE);
}
public static Loader getLoader(String propertiesFile) throws IOException {
/* Read properties file */
Properties properties = new Properties();
properties.load(Loader.class.getClassLoader().getResourceAsStream(propertiesFile));
/* Initialise loader */
return new Loader(properties);
}
public Lirc getLirc() {
return pico.getComponent(Lirc.class);
}
public Work getServer() {
return (Work) pico.getComponent(LircServer.class);
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.button;
public enum ColorButton {
RED, GREEN, YELLOW, BLUE;
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.button;
public enum NumberButton {
ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
}

View File

@@ -0,0 +1,5 @@
package com.github.boukefalos.lirc.button;
public interface RemoteButton {
}

View File

@@ -0,0 +1,66 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.button.remote;
import com.github.boukefalos.lirc.button.RemoteButton;
public enum DenonRC176Button implements RemoteButton {
TAPE_AB ("TAPE_AB"),
TAPE_REC ("TAPE_REC"),
TAPE_PAUSE ("TAPE_PAUSE"),
TAPE_STOP ("TAPE_STOP"),
TAPE_REWIND ("TAPE_REW"),
TAPE_FORWARD ("TAPE_FF"),
TAPE_PREIVOUS ("TAPE_PLAYREV"),
TAPE_NEXT ("TAPE_PLAY"),
CD_PREVIOUS ("CD_TRACK_-"),
CD_NEXT ("CD_TRACK_+"),
CD_SHUFFLE ("CD_RANDOM"),
CD_REPEAT ("CD_REPEAT"),
CD_SKIP ("CD_SKIP"),
CD_PAUSE ("CD_PAUSE"),
CD_STOP ("CD_STOP"),
CD_PLAY ("CD_PLAY"),
AMP_TAPE2 ("AMP_TAPE2"),
AMP_TAPE1 ("AMP_TAPE1"),
AMP_AUX ("AMP_AUX"),
AMP_TUNER ("AMP_TUNER"),
AMP_CD ("AMP_CD"),
AMP_PHONO ("AMP_PHONO"),
AMP_VOLUME_UP ("AMP_VOL_UP"),
AMP_VOLUME_DOWN ("AMP_VOL_DOWN"),
AMP_POWER ("AMP_POWER"),
AMP_MUTE ("AMP_MUTE"),
TUNER_UP ("TUN_CH_UP"),
TUNER_DOWN ("TUN_CH_DOWN");
public static final String NAME = "DENON_RC-176";
protected String code;
private DenonRC176Button(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public String getRemote() {
return NAME;
}
}

View File

@@ -0,0 +1,73 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.button.remote;
import com.github.boukefalos.lirc.button.RemoteButton;
public enum PhiliphsRCLE011Button implements RemoteButton {
POWER ("Standby"),
RED ("Red"),
GREEN ("Green"),
YELLOW ("Yellow"),
BLUE ("Blue"),
TUNE ("Tune"),
RADIO ("Radio"),
SQUARE ("Square"),
MENU ("Menu"),
TEXT ("Text"),
UP ("Up"),
DOWN ("Down"),
LEFT ("Left"),
RIGHT ("Right"),
VOLUME_UP ("Volume+"),
VOLUME_DOWN ("Volume-"),
MUTE ("Mute"),
PROGRAM_UP ("Program+"),
PROGRAM_DOWN ("Program-"),
ONE ("1"),
TWO ("2"),
THREE ("3"),
FOUR ("4"),
FIVE ("5"),
SIX ("6"),
SEVEN ("7"),
EIGHT ("8"),
NINE ("9"),
ZERO ("0"),
CLOCK ("Clock"),
OUT ("Out"),
INFO ("i+"),
SCREEN_UP ("screenup"),
SCREEN_DOWN ("screendown"),
QUESTION ("question");
public static final String NAME = "Philips_RCLE011";
protected String code;
private PhiliphsRCLE011Button(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public String getRemote() {
return NAME;
}
}

View File

@@ -0,0 +1,86 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.button.remote;
import com.github.boukefalos.lirc.button.RemoteButton;
public enum SamsungBN5901015AButton implements RemoteButton {
POWER ("Power"),
SOURCE ("Source"),
ONE ("1"),
TWO ("2"),
THREE ("3"),
FOUR ("4"),
FIVE ("5"),
SIX ("6"),
SEVEN ("7"),
EIGHT ("8"),
NINE ("9"),
ZERO ("0"),
TEXT ("TTX/Mix"),
CHANNEL_TOGGLE ("Pre-Ch"),
VOLUME_DOWN ("Vol+"),
VOLUME_UP ("Vol-"),
MUTE ("Mute"),
CHANNEL_LIST ("Ch.List"),
CHANNEL_NEXT ("Ch+"),
CHANNEL_PREVIOUS ("Ch-"),
MEDIA ("Media.P"),
MENU ("Menu"),
GUIDE ("Guide"),
TOOLS ("Tools"),
UP ("Up"),
INFO ("Info"),
RETURN ("Return"),
EXIT ("Exit"),
LEFT ("Left"),
ENTER ("Enter"),
RIGHT ("Right"),
DOWN ("Down"),
RED ("Red"),
GREEN ("Green"),
YELLOW ("Yellow"),
BLUE ("Blue"),
MODE_P ("P.Mode"),
MODE_S ("S.Mode"),
SIZE_P ("P.Size"),
Dual ("Dual"),
AUDIO ("AD"),
SUBTITLE ("Subt."),
REWIND ("Rewind"),
PAUSE ("Pause"),
FORWARD ("Forward"),
RECORD ("Record"),
PLAY ("Play"),
STOP ("Stop");
public static final String NAME = "Samsung_BN59-01015A";
protected String code;
private SamsungBN5901015AButton(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public String getRemote() {
return NAME;
}
}

View File

@@ -0,0 +1,44 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.button.remote;
import com.github.boukefalos.lirc.button.RemoteButton;
public enum WC02IPOButton implements RemoteButton {
MINUS ("MINUS"),
PLUS ("PLUS"),
NEXT ("NEXT"),
PREVIOUS ("PREVIOUS"),
PLAY ("PLAY"),
HOLD ("HOLD");
public static final String NAME = "WC02-IPO";
protected String code;
private WC02IPOButton(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public String getRemote() {
return NAME;
}
}

View File

@@ -0,0 +1,23 @@
package com.github.boukefalos.lirc.client;
import java.nio.channels.SocketChannel;
import base.server.channel.TcpServerClient;
import com.github.boukefalos.lirc.server.LircTcpServer;
public class LircTcpClient extends TcpServerClient {
protected LircTcpServer server;
public LircTcpClient(LircTcpServer server, SocketChannel socketChannel, Integer bufferSize) {
super(server, socketChannel, bufferSize);
this.server = server;
}
public void receive(byte[] buffer) {
System.err.println(123);
System.err.println(new String(buffer).trim());
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.exception;
public class ButtonException extends Exception {
protected static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,23 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.exception.button;
import com.github.boukefalos.lirc.exception.ButtonException;
public class UnknownButtonException extends ButtonException {
protected static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,23 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.exception.button;
import com.github.boukefalos.lirc.exception.ButtonException;
public class UnknownDirectionException extends ButtonException {
protected static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,115 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.implementation;
import java.util.ArrayList;
import lirc.Lirc.Color;
import lirc.Lirc.Direction;
import lirc.Lirc.Number;
import lirc.Lirc.Signal;
import base.exception.worker.ActivateException;
import base.exception.worker.DeactivateException;
import base.work.Listen;
import com.github.boukefalos.lirc.Lirc;
import com.github.boukefalos.lirc.LircButton;
import com.github.boukefalos.lirc.LircClient;
import com.github.boukefalos.lirc.util.Multiplexer;
import com.github.boukefalos.lirc.util.SignalObject;
public class LocalImplementation extends Listen<Object> implements Lirc {
protected ArrayList<Listen<Object>> listenList;
protected Multiplexer<String> multiplexer;
protected LircClient lircService;
public LocalImplementation() {
listenList = new ArrayList<Listen<Object>>();
lircService = new LircClient();
lircService.register(this);
multiplexer = new Multiplexer<String>();
multiplexer.register(this);
}
public void register(Listen<Object> listen) {
listenList.add(listen);
}
public void remove(Listen<Object> listen) {
listenList.remove(listen);
}
public void activate() throws ActivateException {
logger.debug("Activate " + getClass().getSimpleName());
lircService.start();
super.activate();
}
public void deactivate() throws DeactivateException {
logger.debug("Deactivate LircDevice");
super.deactivate();
lircService.stop();
multiplexer.stop();
}
public void exit() {
logger.debug("Exit LircDevice");
super.exit();
lircService.exit();
multiplexer.exit();
}
public void input(String input) {
multiplexer.add(input);
}
public void input(SignalObject<Object> signalObject) {
Object object = signalObject.object;
if (object instanceof String) {
// Translate String signal objects to LircButton signalObjects
String[] input = ((String) object).split(" ");
LircButton lircButton = new LircButton(input[0], input[1]);
signalObject = new SignalObject<Object>(signalObject.signal, lircButton);
otherParsings(signalObject.signal, input[1].toUpperCase());
}
// Pass signalObject to listens
for (Listen<Object> listen : listenList) {
listen.add(signalObject);
}
}
protected void otherParsings(Signal signal, String code) {
for (Color color : Color.values()) {
if (color.toString().equals(code)) {
add(new SignalObject<Color>(signal, color));
}
}
for (Number number : Number.values()) {
if (number.toString().equals(code)) {
add(new SignalObject<Number>(signal, number));
}
}
for (Direction direction : Direction.values()) {
if (direction.toString().equals(code)) {
add(new SignalObject<Direction>(signal, direction));
}
}
try {
add(new SignalObject<Number>(signal, Number.valueOf(Integer.valueOf(code))));
} catch (NumberFormatException e) {}
}
}

View File

@@ -0,0 +1,51 @@
package com.github.boukefalos.lirc.implementation;
import java.util.ArrayList;
import base.exception.worker.ActivateException;
import base.receiver.Receiver;
import base.server.socket.TcpClient; // Change to channel?
import base.work.Listen;
import com.github.boukefalos.lirc.Lirc;
import com.github.boukefalos.lirc.listen.ClientListen;
import com.github.boukefalos.server.helper.ServerHelper;
// Fix dual Receiver and Sender roles
public class TcpImplementation extends TcpClient implements Lirc, Receiver {
protected ArrayList<Listen<Object>> listenList;
protected ClientListen listen;
public TcpImplementation(String host, int port) {
super(host, port);
listenList = new ArrayList<Listen<Object>>();
listen = new ClientListen(this);
register(this);
}
public void activate() throws ActivateException {
listen.start();
super.activate();
}
public void receive(byte[] buffer) {
// Decode byte array
ServerHelper.receive(this, buffer);
}
public void register(Listen<Object> listen) {
listenList.add(listen);
}
public void add(Object object) {
// Receive decoded object from ServerHelper
listen.add(object);
}
public void input(Object object) {
// Forward to all listens
for (Listen<Object> listen : listenList) {
listen.add(object);
}
}
}

View File

@@ -0,0 +1,40 @@
package com.github.boukefalos.lirc.implementation;
import java.net.UnknownHostException;
import base.sender.UdpSender;
import base.work.Listen;
import com.github.boukefalos.lirc.Lirc;
public class UdpImplementation extends UdpSender implements Lirc {
public UdpImplementation(String host, int port) throws UnknownHostException {
super(host, port);
}
@Override
public void start() {
// TODO Auto-generated method stub
}
@Override
public void register(Listen<Object> listen) {
// TODO Auto-generated method stub
}
@Override
public void add(Object object) {
// TODO Auto-generated method stub
}
@Override
public void input(Object object) {
// TODO Auto-generated method stub
}
// add way to receive udp packets
}

View File

@@ -0,0 +1,19 @@
package com.github.boukefalos.lirc.listen;
import base.work.Listen;
import com.github.boukefalos.lirc.Lirc;
public class ClientListen extends Listen<Object> {
protected Lirc lirc;
public ClientListen(Lirc lirc) {
this.lirc = lirc;
}
public void input(Object object) {
lirc.input(object);
}
// forward send requests to sender
}

View File

@@ -0,0 +1,58 @@
package com.github.boukefalos.lirc.listen;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import lirc.Lirc.Button;
import lirc.Lirc.Button.Builder;
import lirc.Lirc.Button.Type;
import lirc.Lirc.Color;
import lirc.Lirc.ColorButton;
import lirc.Lirc.Direction;
import lirc.Lirc.DirectionButton;
import lirc.Lirc.Number;
import lirc.Lirc.NumberButton;
import lirc.Lirc.Signal;
import base.sender.Sender;
import base.work.Listen;
import com.github.boukefalos.lirc.LircButton;
import com.github.boukefalos.lirc.util.SignalObject;
public class ServerListen extends Listen<Object> {
protected Sender sender;
public ServerListen(Sender sender) {
this.sender = sender;
}
public void input(SignalObject<Object> signalObject) {
Signal signal = signalObject.signal;
Object object = signalObject.object;
Builder builder = Button.newBuilder().setSignal(signal);
if (object instanceof LircButton) {
builder.setType(Type.LIRC);
LircButton lircButton = (LircButton) object;
builder.setLircButton(lircButton.getProto());
} else if (object instanceof Color) {
builder.setType(Type.COLOR);
Color color = (Color) object;
builder.setColorButton(ColorButton.newBuilder().setColor(color));
} else if (object instanceof Number) {
builder.setType(Type.NUMBER);
Number number = (Number) object;
builder.setNumberButton(NumberButton.newBuilder().setNumber(number));
} else if (object instanceof Direction) {
builder.setType(Type.DIRECTION);
Direction direction = (Direction) object;
builder.setDirectionButton(DirectionButton.newBuilder().setDirection(direction));
}
ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
try {
builder.build().writeDelimitedTo(output);
sender.send(output.toByteArray());
} catch (IOException e) {
logger.error("Failed to send command");
}
}
}

View File

@@ -0,0 +1,5 @@
package com.github.boukefalos.lirc.server;
public interface LircServer {
}

View File

@@ -0,0 +1,30 @@
package com.github.boukefalos.lirc.server;
import base.exception.worker.ActivateException;
import base.server.channel.TcpServer;
import com.github.boukefalos.lirc.Lirc;
import com.github.boukefalos.lirc.listen.ServerListen;
import com.github.boukefalos.server.helper.ServerHelper;
public class LircTcpServer extends TcpServer implements LircServer {
protected Lirc lirc;
protected ServerListen listen;
public LircTcpServer(Lirc lirc, int port, Class<?> clientClass) {
super(port, clientClass);
this.lirc = lirc;
listen = new ServerListen(this);
lirc.register(listen);
}
public void activate() throws ActivateException {
lirc.start();
listen.start();
super.activate();
}
public void receive(byte[] buffer) {
ServerHelper.receive(lirc, buffer);
}
}

View File

@@ -0,0 +1,24 @@
package com.github.boukefalos.lirc.server;
import base.server.datagram.UdpServer;
import com.github.boukefalos.lirc.Lirc;
import com.github.boukefalos.server.helper.ServerHelper;
public class LircUdpServer extends UdpServer implements LircServer {
protected Lirc lirc;
public LircUdpServer(Lirc lirc, int port) {
this(lirc, port, BUFFER_SIZE);
}
public LircUdpServer(Lirc lirc, int port, int bufferSize) {
super(port, bufferSize);
this.lirc = lirc;
this.bufferSize = bufferSize;
}
protected void receive(byte[] buffer) {
ServerHelper.receive(lirc, buffer);
}
}

View File

@@ -0,0 +1,100 @@
/**
* Copyright (C) 2015 Rik Veenboer <rik.veenboer@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.boukefalos.lirc.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import lirc.Lirc.Signal;
import base.work.Listen;
public class Multiplexer<T> {
public static final int TIMEOUT = 150;
protected int timeout;
protected ArrayList<Listen<Object>> listenList;
protected ScheduledExecutorService executor;
protected HashMap<T,Integer> counterMap;
public Multiplexer() {
this(TIMEOUT);
}
public Multiplexer(int timeout) {
this.timeout = timeout;
listenList = new ArrayList<Listen<Object>>();
executor = Executors.newSingleThreadScheduledExecutor();
counterMap = new HashMap<T,Integer>();
}
public void register(Listen<Object> listen) {
listenList.add(listen);
}
public void remove(Listen<SignalObject<T>> listen) {
listenList.remove(listen);
}
public synchronized void add(T object) {
Expire expire = new Expire(this, object);
executor.schedule(expire, (long) timeout, TimeUnit.MILLISECONDS);
int counter = counterMap.getOrDefault(object, 0);
if (counter == 0) {
for (Listen<Object> listen : listenList) {
listen.add(new SignalObject<T>(Signal.BEGIN, object));
}
}
counterMap.put(object, counter + 1);
}
protected synchronized void expire(T object) {
int counter = counterMap.get(object);
counterMap.put(object, counter - 1);
if (counter == 1) {
for (Listen<Object> listen : listenList) {
listen.add(new SignalObject<T>(Signal.END, object));
}
}
}
public class Expire implements Runnable {
protected Multiplexer<T> multiplexer;
protected T object;
public Expire(Multiplexer<T> multiplexer, T object) {
this.multiplexer = multiplexer;
this.object = object;
}
public void run() {
multiplexer.expire(object);
}
}
public void stop() {
executor.shutdown();
}
public void exit() {
stop();
// Should cancel all scheduled Runnables
}
}

View File

@@ -0,0 +1,18 @@
package com.github.boukefalos.lirc.util;
import lirc.Lirc.Signal;
public class SignalObject<T> {
public Signal signal;
public T object;
public SignalObject(Signal signal, T object) {
this.signal = signal;
this.object = object;
}
public String bla() {
return signal + " " + object;
}
}

View File

@@ -0,0 +1,12 @@
package com.github.boukefalos.server.helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SenderHelper {
protected static Logger logger = LoggerFactory.getLogger(SenderHelper.class);
public static void send(String remote, String code) {
}
}

View File

@@ -0,0 +1,53 @@
package com.github.boukefalos.server.helper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import lirc.Lirc.Button;
import lirc.Lirc.Button.Type;
import lirc.Lirc.Color;
import lirc.Lirc.Direction;
import lirc.Lirc.Number;
import lirc.Lirc.Signal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.boukefalos.lirc.Lirc;
import com.github.boukefalos.lirc.LircButton;
import com.github.boukefalos.lirc.util.SignalObject;
public class ServerHelper {
protected static Logger logger = LoggerFactory.getLogger(ServerHelper.class);
public static void receive(Lirc lirc, byte[] buffer) {
ByteArrayInputStream input = new ByteArrayInputStream(buffer);
try {
Button button = Button.parseDelimitedFrom(input);
Type type = button.getType();
Signal signal = button.getSignal();
// Use switch-case statements
if (button.hasColorButton()) {
Color color = button.getColorButton().getColor();
lirc.add(new SignalObject<Object>(signal, color));
}
if (button.hasDirectionButton()) {
Direction direction = button.getDirectionButton().getDirection();
lirc.add(new SignalObject<Direction>(signal, direction));
}
if (button.hasNumberButton()) {
Number number = button.getNumberButton().getNumber();
lirc.add(new SignalObject<Number>(signal, number));
}
if (button.hasLircButton()) {
String remote = button.getLircButton().getRemote();
String code = button.getLircButton().getCode();
LircButton lircButton = new LircButton(remote, code);
lirc.add(new SignalObject<LircButton>(signal, lircButton));
}
} catch (IOException e) {
logger.error("Failed to parse input");
return;
}
}
}

67
src/main/proto/lirc.proto Normal file
View File

@@ -0,0 +1,67 @@
package proto;
enum Signal {
BEGIN = 1;
END = 2;
NONE = 3;
}
enum Color {
RED = 1;
GREEN = 2;
YELLOW = 3;
BLUE = 4;
}
enum Direction {
UP = 1;
DOWN = 2;
LEFT = 3;
RIGHT = 4;
}
enum Number {
ZERO = 1;
ONE = 2;
TWO = 3;
THREE = 4;
FOUR = 5;
FIVE = 6;
SIX = 7;
SEVEN = 8;
EIGHT = 9;
NINE = 10;
}
message Button {
enum Type {
LIRC = 1;
COLOR = 2;
NUMBER = 3;
DIRECTION = 4;
}
required Signal signal = 1;
required Type type = 2;
optional LircButton lircButton = 3;
optional ColorButton colorButton = 4;
optional NumberButton numberButton = 5;
optional DirectionButton directionButton = 6;
}
message LircButton {
required string remote = 1;
required string code = 2;
}
message ColorButton {
required Color color = 1;
}
message NumberButton {
required Number number = 1;
}
message DirectionButton {
required Direction direction = 1;
}

View File

@@ -0,0 +1,43 @@
package test;
import lirc.Lirc.Signal;
import base.exception.worker.ActivateException;
import base.work.Listen;
import com.github.boukefalos.lirc.LircButton;
import com.github.boukefalos.lirc.implementation.LocalImplementation;
import com.github.boukefalos.lirc.util.SignalObject;
public class Test extends Listen<Object> {
public static void main(String[] args) {
new Test().start();
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {}
}
protected LocalImplementation lirc;
public Test() {
lirc = new LocalImplementation();
lirc.register(this);
}
public void activate() throws ActivateException {
logger.debug("Activate " + getClass().getSimpleName());
lirc.start();
super.activate();
}
public void start() {
super.start();
}
public void input(SignalObject<LircButton> lircButtonSignal) {
Signal signal = lircButtonSignal.signal;
LircButton lircButton = lircButtonSignal.object;
String code = lircButton.code;
logger.error(signal.name() + " : " + code + " @ " + lircButton.remote);
}
}