public class MjComTalker {
private static final int MAX_DELAY = 3000;
private static final int STX = 0x82;
private static final int STX_HOLE = 0x00;
private static final int STX_HEAD = 0xAA;
private static final int STX_TAIL = 0x55;
private static final String NONAME = new String(new byte[]{0,0,0,0,0,0,0,0});
private static final short EMPTY_SHORT_ARRAY[] = {};
private static final byte EMPTY_BYTE_ARRAY[] = {};
public static String TEST_IP = "192.168.27.234";
// public static String TEST_IP = "localhost";
public static int TEST_PORT = 4001;
/**
* @param args
*/
public static void main(String[] args) throws IOException {
MjComTalker talker = new MjComTalker(TEST_IP, TEST_PORT);
short[] stateList2 = null;
System.out.println(new Date());
long beg = System.nanoTime();
if (talker.isAfterVersion(1, 6)) {
for (int i = 0; i < 10; ++i) {
Random rnd = new Random();
short[] buf = new short[126];
for(int idx=0; idx<buf.length; ++idx)
buf[idx] = (short)(rnd.nextInt(100)+5);
stateList2 = talker.readDeviceAddress(1, buf);
if (stateList2.length>0)
System.out.println(rnd.nextInt());
else
System.out.println("failed read");
}
}
long end = System.nanoTime();
System.out.println("10 times read cost:");
System.out.println((end-beg) / 1000000);
System.out.println(new Date());
System.out.println("continuous adress:");
for (short i : talker.readDeviceAddress(1, 5, 100)) {
System.out.println(i);
}
System.out.println("discrete single adress:");
for (int i = 0; i < 60; ++i) {
int v = talker.readDeviceAddressWord(1, i);
System.out.println(v);
}
} /**MJCOM的CRC16算法实现
* @param buf CRC16的数据源
* @return CRC16的结果(只有16位有效)
*/
public static int mjComCRC(byte buf[]) {
int len = buf.length;
int crc,chr,i,j;
crc = 0xffff;
for(j=0; j<len; ++j){
chr = buf[j] & 0xff;
crc ^= chr;
for(i=0;i<8;i++) {
if ((crc & 01)!=0)
crc = (crc>>1)^0xa001;
else
crc = crc>>1;
}
crc &= 0xffff;
}
return crc;
}
/**生成stuff串
* @param data
* @return
*/
public static byte[] encodeStuff(byte []data) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
for(byte b: data) {
bytes.write(b);
if (b == (byte)STX) {
bytes.write((byte)STX_HOLE);
}
}
return bytes.toByteArray();
}
/**解码stuff串
* @param data
* @return
*/
public static byte[] decodeStuff(byte []data) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte prevb = (byte)STX_HOLE;
for(byte b: data) {
if (b == (byte)STX_HOLE && prevb == (byte)STX) {
prevb = b;
continue;
}
prevb = b;
bytes.write(b);
}
return bytes.toByteArray();
}
/**生成应用层消息
* @param dev 设备号
* @param func 函数号
* @param data byte数据
* @return 应用层的消息
*/
public static byte[] encodeAppMsg(int dev, int func, byte []data) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bytes.write(dev);
bytes.write(func);
int wordlen = data.length / 2;
bytes.write(wordlen >> 8);
bytes.write(wordlen);
bytes.write(data, 0, data.length);
return bytes.toByteArray();
}
/**解读应用层消息
* @param data 应用层的消息
* @return
*/
public static MjComAppMessage decodeAppMsg(byte []appMsg) {
MjComAppMessage appMessage = new MjComAppMessage();
if (appMsg.length < 4) {
return null;
}
appMessage.setDev(appMsg[0] & 0xff);
appMessage.setFunc(appMsg[1] & 0xff);
int wordLen = ArraysUtils.getWordInBytes(appMsg, 2);
//TODO: when the mjcom 700 device fix the bug , uncomment this code
// if (appMsg.length < wordLen*2 + 4) {
// return null;
// }
appMessage.setWordLen( wordLen );
appMessage.setData(Arrays.copyOfRange(appMsg,
4,
Math.min(4 + wordLen * 2, appMsg.length)));
return appMessage;
}
/**生成网络通讯层消息
* @param appMsg 应用层消息
* @return 网络通讯层消息
*/
public static byte[] encodeNetMsg(byte []appMsg) {
ByteArrayOutputStream bytes_stuff = new ByteArrayOutputStream();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
int dataCRC = mjComCRC(Arrays.copyOfRange(appMsg, 1, appMsg.length));
bytes_stuff.write(appMsg, 0, appMsg.length);
bytes_stuff.write(dataCRC); //CRC填充时用小端结构
bytes_stuff.write(dataCRC >> 8);
byte[] stuffed = encodeStuff(bytes_stuff.toByteArray());
bytes.write(STX);
bytes.write(STX_HEAD);
bytes.write(stuffed, 0, stuffed.length);
bytes.write(STX);
bytes.write(STX_TAIL);
return bytes.toByteArray();
}
/**解码网络通讯层消息
* @param appMsg 应用层消息
* @return 网络通讯层消息
*/
public static byte[] decodeNetMsg(byte []netMsg) {
if (netMsg.length < 4) {
return EMPTY_BYTE_ARRAY;
}
byte[] noSTX = Arrays.copyOfRange(netMsg, 2, netMsg.length - 2);
byte[] unstaffed = decodeStuff(noSTX);
if (unstaffed.length < 2) {
return EMPTY_BYTE_ARRAY;
}
return Arrays.copyOfRange(unstaffed, 0, unstaffed.length - 2); //no CRC
}
private String deviceIpAddress = "";
private int deviceIpPort = 0;
private boolean versionIsAsked = false;
public MjComTalker() {
}
public MjComTalker(String deviceIpAddress, int deviceIpPort) {
this.deviceIpAddress = deviceIpAddress;
this.deviceIpPort = deviceIpPort;
}
public boolean isConnected(){
return false;
} private byte[] MjComTalk(byte[] appMsg) throws IOException {
Socket socket = null;
try {
socket = new ZhiYuanJrTalker(deviceIpAddress, deviceIpPort);
byte[] netMsg = encodeNetMsg(appMsg);
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
out.write(netMsg); //发送消息
out.flush();
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
socket.setSoTimeout(MAX_DELAY);
//long startTime = System.currentTimeMillis();
boolean reachEnd = false;
byte [] buf = new byte[2048];
int len = 0;
byte lastc = 0;
while(!reachEnd && (len = in.read(buf)) > 0) {
if (len > 2 && buf[len-1] == (byte)STX_TAIL && buf[len-2] == (byte)STX) {
reachEnd = true;
}
if (buf[0] == (byte)STX_TAIL && lastc == (byte)STX) {
reachEnd = true;
}
bytes.write(buf, 0, len);
lastc = buf[len-1];
}
return decodeNetMsg(bytes.toByteArray());
}
catch (Exception e) {
return new byte[0];
}
finally{
try{
if (socket!=null)
socket.close();
}catch (Exception e) {
}
}
}
public int getVersion(int dev) {
try {
byte[] appMsg = encodeAppMsg(1, 43, new byte[]{0, 10});
byte[] backMsg = MjComTalk(appMsg);
return backMsg[25];
}catch (Exception e) {
return 0;
}
}
public boolean isAfterVersion(int dev, int version) {
return getVersion(dev) >= version;
}
public short[] readDeviceAddress(int dev, short addrs[]) {
try {
if (true) {
versionIsAsked = isAfterVersion(dev, 6);
}
short[] withHead = ArraysUtils.addShortHead(addrs);
byte[] appMsg = encodeAppMsg(1, 72, ArraysUtils.padShortToByte(withHead));
byte[] backMsg = MjComTalk(appMsg);
MjComAppMessage appMessage = decodeAppMsg(backMsg);
return ArraysUtils.padByteToShort(appMessage.getData());
}catch (Exception e) {
e.printStackTrace();
return EMPTY_SHORT_ARRAY;
}
}
}
private static final int MAX_DELAY = 3000;
private static final int STX = 0x82;
private static final int STX_HOLE = 0x00;
private static final int STX_HEAD = 0xAA;
private static final int STX_TAIL = 0x55;
private static final String NONAME = new String(new byte[]{0,0,0,0,0,0,0,0});
private static final short EMPTY_SHORT_ARRAY[] = {};
private static final byte EMPTY_BYTE_ARRAY[] = {};
public static String TEST_IP = "192.168.27.234";
// public static String TEST_IP = "localhost";
public static int TEST_PORT = 4001;
/**
* @param args
*/
public static void main(String[] args) throws IOException {
MjComTalker talker = new MjComTalker(TEST_IP, TEST_PORT);
short[] stateList2 = null;
System.out.println(new Date());
long beg = System.nanoTime();
if (talker.isAfterVersion(1, 6)) {
for (int i = 0; i < 10; ++i) {
Random rnd = new Random();
short[] buf = new short[126];
for(int idx=0; idx<buf.length; ++idx)
buf[idx] = (short)(rnd.nextInt(100)+5);
stateList2 = talker.readDeviceAddress(1, buf);
if (stateList2.length>0)
System.out.println(rnd.nextInt());
else
System.out.println("failed read");
}
}
long end = System.nanoTime();
System.out.println("10 times read cost:");
System.out.println((end-beg) / 1000000);
System.out.println(new Date());
System.out.println("continuous adress:");
for (short i : talker.readDeviceAddress(1, 5, 100)) {
System.out.println(i);
}
System.out.println("discrete single adress:");
for (int i = 0; i < 60; ++i) {
int v = talker.readDeviceAddressWord(1, i);
System.out.println(v);
}
} /**MJCOM的CRC16算法实现
* @param buf CRC16的数据源
* @return CRC16的结果(只有16位有效)
*/
public static int mjComCRC(byte buf[]) {
int len = buf.length;
int crc,chr,i,j;
crc = 0xffff;
for(j=0; j<len; ++j){
chr = buf[j] & 0xff;
crc ^= chr;
for(i=0;i<8;i++) {
if ((crc & 01)!=0)
crc = (crc>>1)^0xa001;
else
crc = crc>>1;
}
crc &= 0xffff;
}
return crc;
}
/**生成stuff串
* @param data
* @return
*/
public static byte[] encodeStuff(byte []data) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
for(byte b: data) {
bytes.write(b);
if (b == (byte)STX) {
bytes.write((byte)STX_HOLE);
}
}
return bytes.toByteArray();
}
/**解码stuff串
* @param data
* @return
*/
public static byte[] decodeStuff(byte []data) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte prevb = (byte)STX_HOLE;
for(byte b: data) {
if (b == (byte)STX_HOLE && prevb == (byte)STX) {
prevb = b;
continue;
}
prevb = b;
bytes.write(b);
}
return bytes.toByteArray();
}
/**生成应用层消息
* @param dev 设备号
* @param func 函数号
* @param data byte数据
* @return 应用层的消息
*/
public static byte[] encodeAppMsg(int dev, int func, byte []data) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bytes.write(dev);
bytes.write(func);
int wordlen = data.length / 2;
bytes.write(wordlen >> 8);
bytes.write(wordlen);
bytes.write(data, 0, data.length);
return bytes.toByteArray();
}
/**解读应用层消息
* @param data 应用层的消息
* @return
*/
public static MjComAppMessage decodeAppMsg(byte []appMsg) {
MjComAppMessage appMessage = new MjComAppMessage();
if (appMsg.length < 4) {
return null;
}
appMessage.setDev(appMsg[0] & 0xff);
appMessage.setFunc(appMsg[1] & 0xff);
int wordLen = ArraysUtils.getWordInBytes(appMsg, 2);
//TODO: when the mjcom 700 device fix the bug , uncomment this code
// if (appMsg.length < wordLen*2 + 4) {
// return null;
// }
appMessage.setWordLen( wordLen );
appMessage.setData(Arrays.copyOfRange(appMsg,
4,
Math.min(4 + wordLen * 2, appMsg.length)));
return appMessage;
}
/**生成网络通讯层消息
* @param appMsg 应用层消息
* @return 网络通讯层消息
*/
public static byte[] encodeNetMsg(byte []appMsg) {
ByteArrayOutputStream bytes_stuff = new ByteArrayOutputStream();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
int dataCRC = mjComCRC(Arrays.copyOfRange(appMsg, 1, appMsg.length));
bytes_stuff.write(appMsg, 0, appMsg.length);
bytes_stuff.write(dataCRC); //CRC填充时用小端结构
bytes_stuff.write(dataCRC >> 8);
byte[] stuffed = encodeStuff(bytes_stuff.toByteArray());
bytes.write(STX);
bytes.write(STX_HEAD);
bytes.write(stuffed, 0, stuffed.length);
bytes.write(STX);
bytes.write(STX_TAIL);
return bytes.toByteArray();
}
/**解码网络通讯层消息
* @param appMsg 应用层消息
* @return 网络通讯层消息
*/
public static byte[] decodeNetMsg(byte []netMsg) {
if (netMsg.length < 4) {
return EMPTY_BYTE_ARRAY;
}
byte[] noSTX = Arrays.copyOfRange(netMsg, 2, netMsg.length - 2);
byte[] unstaffed = decodeStuff(noSTX);
if (unstaffed.length < 2) {
return EMPTY_BYTE_ARRAY;
}
return Arrays.copyOfRange(unstaffed, 0, unstaffed.length - 2); //no CRC
}
private String deviceIpAddress = "";
private int deviceIpPort = 0;
private boolean versionIsAsked = false;
public MjComTalker() {
}
public MjComTalker(String deviceIpAddress, int deviceIpPort) {
this.deviceIpAddress = deviceIpAddress;
this.deviceIpPort = deviceIpPort;
}
public boolean isConnected(){
return false;
} private byte[] MjComTalk(byte[] appMsg) throws IOException {
Socket socket = null;
try {
socket = new ZhiYuanJrTalker(deviceIpAddress, deviceIpPort);
byte[] netMsg = encodeNetMsg(appMsg);
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
out.write(netMsg); //发送消息
out.flush();
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
socket.setSoTimeout(MAX_DELAY);
//long startTime = System.currentTimeMillis();
boolean reachEnd = false;
byte [] buf = new byte[2048];
int len = 0;
byte lastc = 0;
while(!reachEnd && (len = in.read(buf)) > 0) {
if (len > 2 && buf[len-1] == (byte)STX_TAIL && buf[len-2] == (byte)STX) {
reachEnd = true;
}
if (buf[0] == (byte)STX_TAIL && lastc == (byte)STX) {
reachEnd = true;
}
bytes.write(buf, 0, len);
lastc = buf[len-1];
}
return decodeNetMsg(bytes.toByteArray());
}
catch (Exception e) {
return new byte[0];
}
finally{
try{
if (socket!=null)
socket.close();
}catch (Exception e) {
}
}
}
public int getVersion(int dev) {
try {
byte[] appMsg = encodeAppMsg(1, 43, new byte[]{0, 10});
byte[] backMsg = MjComTalk(appMsg);
return backMsg[25];
}catch (Exception e) {
return 0;
}
}
public boolean isAfterVersion(int dev, int version) {
return getVersion(dev) >= version;
}
public short[] readDeviceAddress(int dev, short addrs[]) {
try {
if (true) {
versionIsAsked = isAfterVersion(dev, 6);
}
short[] withHead = ArraysUtils.addShortHead(addrs);
byte[] appMsg = encodeAppMsg(1, 72, ArraysUtils.padShortToByte(withHead));
byte[] backMsg = MjComTalk(appMsg);
MjComAppMessage appMessage = decodeAppMsg(backMsg);
return ArraysUtils.padByteToShort(appMessage.getData());
}catch (Exception e) {
e.printStackTrace();
return EMPTY_SHORT_ARRAY;
}
}
}
还是没有搞定呀..我都快烦死了...
不知道怎么发送和接收二制数到单片那边去....
记得那句话怎么说来着:"虽然这只是100分,但这已是我的全部啊!!!!".