2013-01-09 11:40:38 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2013 The Netty Project
|
|
|
|
*
|
|
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
|
|
* with the License. You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*/
|
2013-01-14 21:34:58 +01:00
|
|
|
package io.netty.channel.rxtx;
|
2013-01-09 11:40:38 +01:00
|
|
|
|
2013-05-17 12:20:46 +02:00
|
|
|
import gnu.io.CommPort;
|
|
|
|
import gnu.io.CommPortIdentifier;
|
|
|
|
import gnu.io.SerialPort;
|
2013-01-21 15:12:23 +01:00
|
|
|
import io.netty.channel.ChannelPromise;
|
2013-02-01 10:32:27 +01:00
|
|
|
import io.netty.channel.oio.OioByteStreamChannel;
|
2013-01-21 10:14:21 +01:00
|
|
|
|
2013-01-09 11:40:38 +01:00
|
|
|
import java.net.SocketAddress;
|
2013-01-21 15:12:23 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2013-01-09 11:40:38 +01:00
|
|
|
|
2013-05-17 12:20:46 +02:00
|
|
|
import static io.netty.channel.rxtx.RxtxChannelOption.*;
|
2013-01-09 11:40:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A channel to a serial device using the RXTX library.
|
|
|
|
*/
|
2013-01-21 12:10:07 +01:00
|
|
|
public class RxtxChannel extends OioByteStreamChannel {
|
2013-01-10 06:01:17 +01:00
|
|
|
|
|
|
|
private static final RxtxDeviceAddress LOCAL_ADDRESS = new RxtxDeviceAddress("localhost");
|
2013-01-09 11:40:38 +01:00
|
|
|
|
2013-01-10 06:01:17 +01:00
|
|
|
private final RxtxChannelConfig config;
|
2013-01-09 11:40:38 +01:00
|
|
|
|
2013-01-10 06:01:17 +01:00
|
|
|
private boolean open = true;
|
2013-01-09 11:40:38 +01:00
|
|
|
private RxtxDeviceAddress deviceAddress;
|
|
|
|
private SerialPort serialPort;
|
|
|
|
|
|
|
|
public RxtxChannel() {
|
2013-07-09 07:49:06 +02:00
|
|
|
super(null);
|
2013-01-09 11:40:38 +01:00
|
|
|
|
2013-01-20 11:18:40 +01:00
|
|
|
config = new DefaultRxtxChannelConfig(this);
|
2013-01-09 11:40:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2013-01-10 06:01:17 +01:00
|
|
|
public RxtxChannelConfig config() {
|
2013-01-09 11:40:38 +01:00
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isOpen() {
|
2013-01-10 06:01:17 +01:00
|
|
|
return open;
|
2013-01-09 11:40:38 +01:00
|
|
|
}
|
|
|
|
|
2013-01-21 15:12:23 +01:00
|
|
|
@Override
|
|
|
|
protected AbstractUnsafe newUnsafe() {
|
|
|
|
return new RxtxUnsafe();
|
|
|
|
}
|
|
|
|
|
2013-01-09 11:40:38 +01:00
|
|
|
@Override
|
|
|
|
protected void doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
|
|
|
|
RxtxDeviceAddress remote = (RxtxDeviceAddress) remoteAddress;
|
2013-01-17 07:06:46 +01:00
|
|
|
final CommPortIdentifier cpi = CommPortIdentifier.getPortIdentifier(remote.value());
|
2013-01-09 11:40:38 +01:00
|
|
|
final CommPort commPort = cpi.open(getClass().getName(), 1000);
|
2014-02-22 14:04:11 +01:00
|
|
|
commPort.enableReceiveTimeout(config().getOption(READ_TIMEOUT));
|
2013-01-09 11:40:38 +01:00
|
|
|
deviceAddress = remote;
|
|
|
|
|
|
|
|
serialPort = (SerialPort) commPort;
|
2013-01-21 15:12:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void doInit() throws Exception {
|
2013-01-09 11:40:38 +01:00
|
|
|
serialPort.setSerialPortParams(
|
2013-01-21 15:12:23 +01:00
|
|
|
config().getOption(BAUD_RATE),
|
|
|
|
config().getOption(DATA_BITS).value(),
|
|
|
|
config().getOption(STOP_BITS).value(),
|
|
|
|
config().getOption(PARITY_BIT).value()
|
2013-01-09 11:40:38 +01:00
|
|
|
);
|
|
|
|
serialPort.setDTR(config().getOption(DTR));
|
|
|
|
serialPort.setRTS(config().getOption(RTS));
|
|
|
|
|
2013-01-21 10:14:21 +01:00
|
|
|
activate(serialPort.getInputStream(), serialPort.getOutputStream());
|
2013-01-09 11:40:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2013-01-10 06:01:17 +01:00
|
|
|
public RxtxDeviceAddress localAddress() {
|
|
|
|
return (RxtxDeviceAddress) super.localAddress();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RxtxDeviceAddress remoteAddress() {
|
|
|
|
return (RxtxDeviceAddress) super.remoteAddress();
|
2013-01-09 11:40:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2013-01-10 06:01:17 +01:00
|
|
|
protected RxtxDeviceAddress localAddress0() {
|
|
|
|
return LOCAL_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected RxtxDeviceAddress remoteAddress0() {
|
2013-01-09 11:40:38 +01:00
|
|
|
return deviceAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void doBind(SocketAddress localAddress) throws Exception {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void doDisconnect() throws Exception {
|
|
|
|
doClose();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void doClose() throws Exception {
|
2013-01-10 06:01:17 +01:00
|
|
|
open = false;
|
2013-01-09 11:40:38 +01:00
|
|
|
try {
|
2013-01-21 10:14:21 +01:00
|
|
|
super.doClose();
|
|
|
|
} finally {
|
|
|
|
if (serialPort != null) {
|
|
|
|
serialPort.removeEventListener();
|
|
|
|
serialPort.close();
|
|
|
|
serialPort = null;
|
2013-01-09 11:40:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-01-21 15:12:23 +01:00
|
|
|
|
|
|
|
private final class RxtxUnsafe extends AbstractUnsafe {
|
|
|
|
@Override
|
|
|
|
public void connect(
|
|
|
|
final SocketAddress remoteAddress,
|
|
|
|
final SocketAddress localAddress, final ChannelPromise promise) {
|
2014-02-10 23:04:47 +01:00
|
|
|
if (!promise.setUncancellable() || !ensureOpen(promise)) {
|
2013-05-17 12:20:46 +02:00
|
|
|
return;
|
|
|
|
}
|
2013-01-21 15:12:23 +01:00
|
|
|
|
2013-05-17 12:20:46 +02:00
|
|
|
try {
|
|
|
|
final boolean wasActive = isActive();
|
|
|
|
doConnect(remoteAddress, localAddress);
|
|
|
|
|
|
|
|
int waitTime = config().getOption(WAIT_TIME);
|
|
|
|
if (waitTime > 0) {
|
|
|
|
eventLoop().schedule(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
doInit();
|
2014-02-10 23:52:24 +01:00
|
|
|
safeSetSuccess(promise);
|
2013-05-17 12:20:46 +02:00
|
|
|
if (!wasActive && isActive()) {
|
|
|
|
pipeline().fireChannelActive();
|
2013-01-21 15:12:23 +01:00
|
|
|
}
|
2013-05-17 12:20:46 +02:00
|
|
|
} catch (Throwable t) {
|
2014-02-10 23:52:24 +01:00
|
|
|
safeSetFailure(promise, t);
|
2013-05-17 12:20:46 +02:00
|
|
|
closeIfClosed();
|
2013-01-21 15:12:23 +01:00
|
|
|
}
|
|
|
|
}
|
2013-05-17 12:20:46 +02:00
|
|
|
}, waitTime, TimeUnit.MILLISECONDS);
|
|
|
|
} else {
|
|
|
|
doInit();
|
2014-02-10 23:52:24 +01:00
|
|
|
safeSetSuccess(promise);
|
2013-05-17 12:20:46 +02:00
|
|
|
if (!wasActive && isActive()) {
|
|
|
|
pipeline().fireChannelActive();
|
2013-01-21 15:12:23 +01:00
|
|
|
}
|
|
|
|
}
|
2013-05-17 12:20:46 +02:00
|
|
|
} catch (Throwable t) {
|
2014-02-10 23:52:24 +01:00
|
|
|
safeSetFailure(promise, t);
|
2013-05-17 12:20:46 +02:00
|
|
|
closeIfClosed();
|
2013-01-21 15:12:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-01-09 11:40:38 +01:00
|
|
|
}
|