package promauto.jroboplc;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
//import org.apache.log4j.Logger;
import promauto.utils.RpHyperstring;
import promauto.utils.RpSerialPort;
import promauto.utils.RpSerialPortRXTX;
public class SvcSerial extends Service implements IConsoleCmd {
// private static Logger logger = Logger.getLogger(SvcSerial.class);
private HashMap<Integer,RpSerialPort> ports;
@Override
public String getServiceName() {
return "serial";
}
@Override
public boolean load() {
boolean result = super.load();
ports = new HashMap<Integer,RpSerialPort>();
String tmpl = getServiceName() + ".port";
String s;
Set<Map.Entry<Object,Object>> map = JRoboPLC.props.entrySet();
for (Map.Entry<Object,Object> m: map) {
s = m.getKey().toString();
if (s.startsWith(tmpl)) {
int portnum = Integer.parseInt( s.substring(tmpl.length()) );
String[] p = m.getValue().toString().split("\\s*,\\s*");
try {
if (p.length!=6)
throw new NumberFormatException();
int baud = Integer.parseInt(p[1]);
int databits = Integer.parseInt(p[2]);
int parity = convertCharParity(p[3]);
int stopbits = Integer.parseInt(p[4]);
int timeout = Integer.parseInt(p[5]);
RpSerialPort port = new RpSerialPortRXTX();
port.setPortParameters(p[0], baud, databits, parity, stopbits, timeout);
ports.put(portnum, port);
}
catch (NumberFormatException e) {
JRoboUtils.logError(
JRoboStrings.INVALID_SERIAL_CFG + m.getKey() +
"=" + m.getValue());
result = false;
}
}
}
return result;
}
private int convertCharParity(String strParity) throws NumberFormatException {
switch (strParity.charAt(0)) {
case 'N':
return RpSerialPort.PARITY_NONE;
case 'E':
return RpSerialPort.PARITY_EVEN;
case 'O':
return RpSerialPort.PARITY_ODD;
case 'M':
return RpSerialPort.PARITY_MARK;
case 'S':
return RpSerialPort.PARITY_SPACE;
default:
throw new NumberFormatException();
}
}
@Override
public boolean initialize() {
// set up RXTX property
StringBuilder sb = new StringBuilder();
for (RpSerialPort port: ports.values()) {
if (sb.length()>0)
sb.append(java.io.File.pathSeparator);
sb.append(port.getName());
}
if (sb.length()>0)
super.initialize();
return RpSerialPortRXTX.definePorts(sb.toString());
}
@Override
public boolean start() {
if (ports.size()>0)
super.start();
// open ports
boolean result = true;
for (RpSerialPort port: ports.values())
if (!(result = port.open()))
break;
return result;
}
@Override
public boolean closedown() {
if (!loaded)
return true;
if (ports!=null) {
if (ports.size()>0)
super.closedown();
// close ports
for (RpSerialPort port: ports.values())
port.close();
}
return true;
}
@Override
public int getStatus() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getStatusStr() {
// TODO Auto-generated method stub
return null;
}
public RpSerialPort getPort(int portnum) {
return ports.get(portnum);
}
private RpSerialPort getPortForConsoleCommand(String[] cmd) throws Exception {
RpSerialPort port = getPort(Integer.parseInt(cmd[2]));
if (port==null)
throw new Exception();
return port;
}
@Override
public boolean processConsoleCommand(SvcConsole svcConsole, int reqId,
String[] cmd) throws Exception {
boolean result = super.processConsoleCommand( svcConsole, reqId, cmd );
if (result) {
// Command - list
if (cmd[1].equals("list") || cmd[1].equals("l")) {
TreeSet<Integer> set = new TreeSet<Integer>( ports.keySet() );
RpSerialPort port;
for (Integer portnum: set) {
port = ports.get(portnum);
svcConsole.write(" " + portnum + ": " +port.getName() + "\n" );
}
} else
// Command - readstr
if (cmd[1].equals("readstr") || cmd[1].equals("rs")) {
RpSerialPort port = getPortForConsoleCommand(cmd);
svcConsole.write(JRoboStrings.SVCSERIAL_READ_FROM + port.getName()+": "+ port.readAllString() +"\n" );
} else
// Command - readhex
if (cmd[1].equals("readhex") || cmd[1].equals("rh")) {
RpSerialPort port = getPortForConsoleCommand(cmd);
byte[] bin = new byte[2048];
int n = port.readBytes(bin);
byte[] bb = Arrays.copyOfRange(bin, 0, Math.abs(n));
svcConsole.write(JRoboStrings.SVCSERIAL_READ_FROM + port.getName()+": "+ RpHyperstring.bytesToHexString(bb) +"\n" );
} else
// Command - write and read string
if (cmd[1].equals("str") || cmd[1].equals("s")) {
RpSerialPort port = getPortForConsoleCommand(cmd);
svcConsole.write(JRoboStrings.SVCSERIAL_WRITE_TO + port.getName()+": "+cmd[3]+"\n" );
port.writeString(cmd[3]+"\n");
Thread.sleep(500);
svcConsole.write(JRoboStrings.SVCSERIAL_READ_FROM + port.getName()+": "+ port.readAllString() +"\n" );
} else
// Command - write and read hex
if (cmd[1].equals("hex") || cmd[1].equals("h")) {
RpSerialPort port = getPortForConsoleCommand(cmd);
byte[] bout = RpHyperstring.hexStringToBytes(cmd, 3);
svcConsole.write(JRoboStrings.SVCSERIAL_WRITE_TO + port.getName()+": "+ RpHyperstring.bytesToHexString(bout) +"\n" );
port.writeBytes(bout);
byte[] bin = new byte[2048];
int n = port.readBytes(bin);
byte[] bb = Arrays.copyOfRange(bin, 0, Math.abs(n));
svcConsole.write(JRoboStrings.SVCSERIAL_READ_FROM + port.getName()+": "+ RpHyperstring.bytesToHexString(bb) +"\n" );
} else
// somebody else's command
result = false;
}
return result;
}
@Override
public void writeConsoleHelp(SvcConsole svcConsole) {
svcConsole.write(
" " + getServiceName() + " l|list\n" +
" " + getServiceName() + " s|str <port> <ascii text>\n" +
" " + getServiceName() + " h|hex <port> <hex values>\n" +
" " + getServiceName() + " rs|readstr <port>\n" +
" " + getServiceName() + " rh|readhex <port>\n" +
""
);
}
}