Blame | Last modification | View Log | RSS feed
/**************************************************************************
* Copyright 2011 Jules White
*
* Licensed 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.
***************************************************************************/
package ioio.debugger.server;
import ioio.debugger.server.NetworkIOIOProtocol.Message;
import ioio.debugger.server.NetworkIOIOProtocol.Message.Builder;
import ioio.debugger.server.NetworkIOIOProtocol.TrackingMessage;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
public class IOIODebuggerServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(IOIODebuggerServerHandler.class.getName());
static final ChannelGroup channels = new DefaultChannelGroup();
private ServerHelper helperClass;
private boolean clientConnected;
public void setServerHelper(ServerHelper helper) {
helperClass = helper;
}
@Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
}
super.handleUpstream(ctx, e);
}
public void broadcast(TrackingMessage msg) {
for (Channel c : channels) {
c.write(msg);
}
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
channels.add(e.getChannel());
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// Unregister the channel from the global channel list
// so the channel does not receive messages anymore.
channels.remove(e.getChannel());
clientConnected = false;
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
TrackingMessage tmsg = (TrackingMessage) e.getMessage();
List<Message> msgList;
// Handle each message depending on the type
switch (tmsg.getType()) {
case 10:
// If there are no clients connected, reply with an ok reponse
if (!clientConnected) {
System.out.println("No clients currently connected, allowing connection");
clientConnected = true;
TrackingMessage newMsg = TrackingMessage.newBuilder()
.setId(0)
.setType(11)
.build();
e.getChannel().write(newMsg);
// Otherwise reply with an error response
} else {
System.out.println("Client currently connected, rejecting connection");
TrackingMessage newMsg = TrackingMessage.newBuilder()
.setId(0)
.setType(12)
.build();
e.getChannel().write(newMsg);
}
break;
case 50:
msgList = tmsg.getMessageList();
for (Message msg : msgList) {
if (msg.getType().compareTo("InAnalog") == 0) {
helperClass.AddNewAnalogIn(msg.getPin(), msg.getFreq());
} else if (msg.getType().compareTo("InDigital") == 0) {
helperClass.AddNewDigitalIn(msg.getPin(), msg.getFreq(), msg.getMode());
} else if (msg.getType().compareTo("OutDigital") == 0) {
helperClass.AddNewDigitalOut(msg.getPin(), msg.getState(), msg.getBoolean());
}
}
break;
case 51:
msgList = tmsg.getMessageList();
for (Message msg : msgList) {
helperClass.StopPin(msg.getPin());
}
break;
case 52:
msgList = tmsg.getMessageList();
for (Message msg : msgList) {
helperClass.RemovePin(msg.getPin());
}
break;
case 70:
msgList = tmsg.getMessageList();
for (Message msg : msgList) {
List<Double> dataList = msg.getDataList();
helperClass.DataRecieved(msg.getPin(), dataList);
}
break;
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(Level.WARNING, "Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
/** Queries if clients are currently connected to the server
*
* @return true if there are clients connected, false otherwise
* */
public boolean areClientsConnected() {
return clientConnected;
}
/** Sends a command to the client to add a new analog input
*
* @param pin - Pin number to add
* @param freq - Frequency that pin should update
*/
public void sendAddNewAnalogIn(int pin, long freq) {
System.out.println("Sending command to add new analog input Pin: " + pin + " Freq: " + freq);
Builder message = Message.newBuilder()
.setPin(pin)
.setFreq(freq)
.setType("InAnalog");
TrackingMessage newMsg = TrackingMessage.newBuilder()
.setId(0)
.setType(50)
.addMessage(message)
.build();
broadcast(newMsg);
}
/** Sends a command to the client to add a new digital input
*
* @param pin - Pin number to add
* @param freq - Frequency that pin should update
* @param mode - Mode that pin should be started in [Float/Pull Up/Pull Down]
*/
public void sendAddNewDigitalIn(int pin, long freq, String mode) {
System.out.println("Sending command to add new digital input Pin: " + pin + " Freq: " + freq + "Mode: " + mode);
Builder message = Message.newBuilder()
.setPin(pin)
.setFreq(freq)
.setMode(mode)
.setType("InDigital");
TrackingMessage newMsg = TrackingMessage.newBuilder()
.setId(0)
.setType(50)
.addMessage(message)
.build();
broadcast(newMsg);
}
/** Sends a command to the client to add a new digital output
*
* @param pin - Pin number to add
* @param state - Initial state of pin [Low/High]
* @param openDrain - Option to start pin in open drain mode [true if yes, false if no]
*/
public void sendAddNewDigitalOut(int pin, String state, boolean openDrain) {
System.out.println("Sending command to add new analog input Pin: " + pin + " InitialState: " + state + " OpenDrainMode: " + openDrain);
Builder message = Message.newBuilder()
.setPin(pin)
.setState(state)
.setBoolean(openDrain)
.setType("OutDigital");
TrackingMessage newMsg = TrackingMessage.newBuilder()
.setId(0)
.setType(50)
.addMessage(message)
.build();
broadcast(newMsg);
}
/** Sends a command to the client to execute a hard reset */
public void sendHardReset() {
TrackingMessage newMsg = TrackingMessage.newBuilder()
.setId(0)
.setType(13)
.build();
broadcast(newMsg);
}
}