org.bidib.jbidib.netbidibsimple.tools.BiDiBPiStandalone Maven / Gradle / Ivy
package org.bidib.jbidib.netbidibsimple.tools;
import java.awt.GraphicsEnvironment;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.bidib.jbidib.netbidibsimple.tools.ui.SwingPairingConnector;
import org.bidib.jbidibc.core.ConnectionListener;
import org.bidib.jbidibc.core.utils.NodeUtils;
import org.bidib.jbidibc.netbidib.NetBidibServer;
import org.bidib.jbidibc.netbidib.NetBidibServerHandler;
import org.bidib.jbidibc.netbidib.adapter.DefaultHostAdapter;
import org.bidib.jbidibc.netbidib.adapter.ScmSerialHostAdapter;
import org.bidib.jbidibc.netbidib.message.BidibLinkData;
import org.bidib.jbidibc.netbidib.pairingstore.LocalPairingStore;
import org.bidib.jbidibc.netbidib.pairingstore.PairingStore;
import org.bidib.jbidibc.pi.BidibPiConnector;
import org.bidib.jbidibc.pi.LedState;
import org.bidib.jbidibc.pi.PairingButtonHandler;
import org.bidib.jbidibc.pi.PairingButtonStateListener;
import org.bidib.jbidibc.pi.PairingConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.beust.jcommander.IDefaultProvider;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import io.netty.channel.group.ChannelGroup;
@Parameters(separators = "=")
public class BiDiBPiStandalone {
private static final Logger LOGGER = LoggerFactory.getLogger(BiDiBPiStandalone.class);
@Parameter(names = {
"-port" }, description = "Port to use, e.g. 'COM1' or '/dev/ttyAMA0'. ", required = true, echoInput = true)
private String portName;
@Parameter(names = {
"-listenHost" }, description = "Hostname to listen, e.g. 'localhost' or '0.0.0.0' to listen on all network interfaces.", echoInput = true)
private String listenHost;
@Parameter(names = {
"-listenPort" }, description = "Network port to listen, default is: '62875'.", echoInput = true)
private Integer listenPort;
@Parameter(arity = 1, names = { "-forceTray" }, description = "Force tray application. ", echoInput = true)
private boolean forceTray;
private PairingConnector connector;
private PairingStore pairingStore;
private volatile AtomicBoolean pairingSupportDisabled = new AtomicBoolean();
private BidibLinkData serverLinkData;
private NetBidibServer netBidibServer;
private static final IDefaultProvider DEFAULT_PROVIDER = new IDefaultProvider() {
@Override
public String getDefaultValueFor(String optionName) {
String defaultValue = null;
switch (optionName) {
case "-listenHost":
defaultValue = "0.0.0.0";
break;
case "-listenPort":
defaultValue = Integer.toString(NetBidibServer.DEFAULT_PORTNUM);
break;
case "-forceTray":
defaultValue = Boolean.toString(Boolean.FALSE);
break;
default:
break;
}
return defaultValue;
}
};
public static void main(String[] args) {
final BiDiBPiStandalone command = new BiDiBPiStandalone();
JCommander jc = null;
try {
jc =
JCommander
.newBuilder().addObject(command).programName(command.getClass().getName())
.defaultProvider(DEFAULT_PROVIDER).build();
jc.parse(args);
command.launch();
}
catch (ParameterException ex) {
LOGGER.warn("Execution of " + command.getClass().getSimpleName() + " command failed: " + ex.getMessage());
StringBuilder sb = new StringBuilder();
jc.usage(sb);
LOGGER.warn(sb.toString());
}
}
public BiDiBPiStandalone() {
}
/**
* Launch the application.
*/
public void launch() {
LOGGER
.info("Start the standalone server. Use backend port: {}, listenHost: {}, listenPort: {}", portName,
listenHost, listenPort);
final ShutdownListener shutdownListener = new ShutdownListener() {
@Override
public void performShutdown() {
initShutdown(netBidibServer);
}
};
// load the pairing store
LOGGER.info("Load the data from the pairing store.");
this.pairingStore = new LocalPairingStore();
this.pairingStore.load();
if (!forceTray) {
// create the pairing connector
try {
this.connector = initializeBidibPiConnector();
}
catch (InvalidPlatformException ex) {
LOGGER.warn("Initialize the BidibPiConnector failed.", ex);
if (GraphicsEnvironment.isHeadless()) {
// non gui mode
LOGGER
.warn(
"##========================================================================================##");
LOGGER
.warn(
"No BidibPiConnector detected. The pairing support is disabled and every partner is accepted.");
LOGGER
.warn(
"##========================================================================================##");
pairingSupportDisabled.set(true);
}
else {
// gui mode
LOGGER
.warn(
"##========================================================================================##");
LOGGER
.warn("No BidibPiConnector detected. The pairing support is provided by the tray application.");
LOGGER
.warn(
"##========================================================================================##");
// add the tray icon that allows pairing
this.connector = new SwingPairingConnector(shutdownListener, pairingStore);
this.connector.connect();
}
}
}
else {
// gui mode
if (GraphicsEnvironment.isHeadless()) {
LOGGER.error("Must not start in headless mode.");
System.exit(1);
}
LOGGER.warn("##========================================================================================##");
LOGGER.warn("Run as tray application is forced. Skip BidibPiConnector.");
LOGGER.warn("The pairing support is provided by the tray application.");
LOGGER.warn("##========================================================================================##");
// add the tray icon that allows pairing
this.connector = new SwingPairingConnector(shutdownListener, pairingStore);
this.connector.connect();
}
// create the host adapter
final DefaultHostAdapter hostAdapter = new ScmSerialHostAdapter();
final BiFunction pairingCallback = (bidibLinkData, pairingTimeout) -> {
LOGGER
.info("The pairing callback is called, bidibLinkData: {}, pairingTimeout: {}", bidibLinkData,
pairingTimeout);
boolean pairingResult = false;
try {
LOGGER.info("Check the pairing store.");
pairingResult = pairingStore.isPaired(bidibLinkData.getUniqueId());
LOGGER.info("Checked the pairing store, paired: {}", pairingResult);
if (!pairingResult) {
LOGGER
.warn("The partner is not enabled in the pairing store: {}",
NodeUtils.getUniqueIdAsString(bidibLinkData.getUniqueId()));
}
}
catch (Exception ex) {
LOGGER.warn("Check the pairing status failed.", ex);
}
if (!pairingResult && pairingSupportDisabled.get()) {
LOGGER.warn("The pairing support is disabled. The partner is accepted!");
pairingResult = true;
}
if (connector != null) {
if (!pairingResult) {
LOGGER.info("Call the connector to accept the partner.");
pairingResult =
connector
.acceptClient(NodeUtils.getUniqueIdAsString(bidibLinkData.getUniqueId()), pairingTimeout);
}
else {
LOGGER.info("The pairing result was fetched from the pairing store.");
connector.setPairingLedState(LedState.on);
connector.showAcceptedClient(NodeUtils.getUniqueIdAsString(bidibLinkData.getUniqueId()));
}
}
LOGGER.info("The pairing result: {}", pairingResult);
return pairingResult;
};
serverLinkData = new BidibLinkData();
// // create my unique id
// byte[] uniqueId = new byte[] { 0x00, 0x00, 0x0D, (byte) 0xFA, 0x01, 0x03, (byte) 0xF1 };
// serverLinkData.setUniqueId(ByteUtils.convertUniqueIdToLong(uniqueId));
// serverLinkData.setProdString("netBiDiB-Gateway");
// serverLinkData.setUserString("Central-Gateway");
// serverLinkData.setProtocolVersion(ProtocolVersion.VERSION_0_8);
final NetBidibServer netBidibServer =
new NetBidibServer(listenHost, listenPort, hostAdapter, portName, serverLinkData) {
@Override
protected NetBidibServerHandler createNetBidibServerHandler(
ChannelGroup channelGroup, final BidibLinkData serverLinkData,
final Consumer lazyInitializationCallback) {
NetBidibServerHandler netBidibServerHandler =
super.createNetBidibServerHandler(channelGroup, serverLinkData, lazyInitializationCallback);
netBidibServerHandler.setPairingStore(pairingStore);
netBidibServerHandler.setPairingCallback(pairingCallback);
// add the connection listener for the remote connection to the client
netBidibServerHandler.addRemoteConnectionListener(new ConnectionListener() {
@Override
public void status(String messageKey) {
LOGGER.info("Status: {}", messageKey);
}
@Override
public void opened(String port) {
}
@Override
public void closed(String port) {
LOGGER.info("The connection to the client was closed.");
if (connector != null) {
connector.showWaitForClient();
}
}
@Override
public void stall(boolean stall) {
// TODO Auto-generated method stub
}
});
return netBidibServerHandler;
}
};
// assign the variable
this.netBidibServer = netBidibServer;
// no pairing button handler if no connector
if (connector != null) {
final PairingButtonStateListener pairingButtonStateListener = new PairingButtonStateListener() {
@Override
public void pairingButtonStateChanged(boolean pressed) {
LOGGER.info("The pairing button state changed, pressed: {}", pressed);
}
};
connector.addPairingButtonStateListener(pairingButtonStateListener);
// add pairing button handler for long press
final PairingButtonHandler pairingButtonStateHandler = new PairingButtonHandler(connector, 5000, 12000);
pairingButtonStateHandler.addLongPressedListener(() -> {
LOGGER.info("The pairing button was pressed long. Clear the pairingStore.");
try {
pairingStore.clear();
pairingStore.store();
}
catch (Exception ex) {
LOGGER.warn("Clear the pairing store failed.", ex);
}
});
connector.addPairingButtonStateListener(pairingButtonStateHandler);
}
netBidibServer.setShutdownHook(new Thread(() -> {
LOGGER.info("Run shutdown hook.");
initShutdown(netBidibServer);
}));
Runtime.getRuntime().addShutdownHook(netBidibServer.getShutdownHook());
netBidibServer.start();
LOGGER.info("Wait for server startup.");
try {
Thread.sleep(500);
LOGGER.info("Wait for shutdown.");
final Object shutdownLock = netBidibServer.getShutdownLock();
synchronized (shutdownLock) {
shutdownLock.wait();
}
}
catch (InterruptedException ex) {
LOGGER.warn("The server was terminated.", ex);
}
finally {
initShutdown(netBidibServer);
}
LOGGER.info("Leave the main.");
System.exit(0);
}
public void initShutdown(final NetBidibServer netBidibServer) {
LOGGER.info("Initialize the shutdown.");
try {
netBidibServer.stop();
}
catch (Exception ex) {
LOGGER.warn("Stop the netBidibServer failed.", ex);
}
try {
if (connector != null) {
LOGGER.info("Close the connector.");
connector.close();
}
}
catch (Exception ex) {
LOGGER.warn("Close the connector failed.", ex);
}
}
private PairingConnector initializeBidibPiConnector() {
LOGGER.info("Initialize the BidibPiConnector.");
BidibPiConnector connector = null;
try {
BidibPiConnector.checkPlatform(BidibPiConnector.PI_CPUINFOFILENAME);
connector = new BidibPiConnector();
connector.connect();
return connector;
}
catch (Exception ex) {
LOGGER.warn("Create and initialize the connector to the Pi failed.", ex);
if (connector != null) {
LOGGER.info("Disconnect and free the pi connector.");
connector.disconnect();
connector = null;
}
throw new InvalidPlatformException("Init the pi connector failed.");
}
catch (Error ex) {
LOGGER.warn("Create and initialize the connector to the Pi failed.", ex);
if (connector != null) {
LOGGER.info("Disconnect and free the pi connector.");
connector.disconnect();
connector = null;
}
throw new InvalidPlatformException("Init the pi connector failed.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy