app/src/main/java/safeluck/drive/evaluation/fragment/TcpFragment.java
@@ -16,12 +16,18 @@ import androidx.lifecycle.Observer; import com.anyun.exam.lib.util.Speaker; import com.anyun.im_lib.util.ByteUtil; import com.google.android.material.textfield.TextInputEditText; import com.safeluck.aykj.utils.BytesUtils; import me.yokeyword.fragmentation.SupportFragment; import safeluck.drive.evaluation.DB.criterias.CriteriaForI; import safeluck.drive.evaluation.DB.criterias.viewmodel.CriteriaIViewModel; import safeluck.drive.evaluation.R; import safeluck.drive.evaluation.im.MessageProcessor; import safeluck.drive.evaluation.platformMessage.GainStuMessage; import safeluck.drive.evaluation.platformMessage.JKClientCommonMessage; import safeluck.drive.evaluation.platformMessage.JKRegisterMessage; import safeluck.drive.evaluation.platformMessage.RegisterMessage; import safeluck.drive.evaluation.im.IMSClientBootstrap; @@ -103,8 +109,9 @@ String userId = "100002"; String token = "token_" + userId; String hosts = "[{\"host\":\"47.93.80.84\", \"port\":12125}]"; // String hosts = "[{\"host\":\"192.168.31.77\", \"port\":12125}]"; // String hosts = "[{\"host\":\"47.93.80.84\", \"port\":12125}]"; // String hosts = "[{\"host\":\"47.93.157.103\", \"port\":2020}]"; String hosts = "[{\"host\":\"192.168.31.77\", \"port\":12125}]"; IMSClientBootstrap.getInstance().init(userId,token,hosts,1); break; @@ -122,12 +129,51 @@ //清除app_status 表 // OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(AppStatusInitWork.class).build(); // WorkManager.getInstance(_mActivity).enqueue(oneTimeWorkRequest); RegisterMessage registerMessage = new RegisterMessage((short)0x802); registerMessage.setCityid((short) 1); registerMessage.setProviceId((short)23); registerMessage.setImei("460123874561"); registerMessage.setModel("123"); registerMessage.setSn("2019101500000001"); // RegisterMessage registerMessage = new RegisterMessage((short)0x802); // registerMessage.setCityid((short) 1); // registerMessage.setProviceId((short)23); // registerMessage.setImei("460123874561"); // registerMessage.setModel("123"); // registerMessage.setSn("2019101500000001"); // GainStuMessage gainStuMessage = new GainStuMessage((short) 0x201); // gainStuMessage.setId("123456789"); // gainStuMessage.setExamaCourse((short) 0); // MessageProcessor.getInstance().sendMessage(gainStuMessage.toBytes()); ByteUtil.str2Bcd("13021245"); String strbcd=ByteUtil.bcd2Str(ByteUtil.str2Bcd("13021245")); Log.i(TAG, "onClick: strbcd="+strbcd); JKRegisterMessage jkRegisterMessage = new JKRegisterMessage(); jkRegisterMessage.setMessageLen(55); // jkRegisterMessage.phone = "13021245"; jkRegisterMessage.phone = "0008618513021245"; jkRegisterMessage.proviceid = 23; jkRegisterMessage.messageId = 0x100; jkRegisterMessage.protocalVer = 235; jkRegisterMessage.cityid = 1; jkRegisterMessage.imei = "460123874561"; jkRegisterMessage.model = "123"; jkRegisterMessage.sn = "0314200100000004"; Log.i(TAG, "onClick: msg len "+jkRegisterMessage.getMessageLen()+" "+ jkRegisterMessage.props.value); byte[] str = jkRegisterMessage.toBytes(); MessageProcessor.getInstance().sendMessage(str); Log.i(TAG, "onClick: "+ BytesUtils.bytesToHexString(str)+" ============"); JKClientCommonMessage jkClientCommonMessage =new JKClientCommonMessage(); jkClientCommonMessage.setMessageLen(5); jkClientCommonMessage.messageId = 0x8100; jkClientCommonMessage.protocalVer = 235; // jkClientCommonMessage.phone = "13021245"; jkClientCommonMessage.respMessageId = "8001"; jkClientCommonMessage.respNo = 15; jkClientCommonMessage.result =1; String str1 = jkClientCommonMessage.toString(); Log.i(TAG, "onClick1: "+ str1+" ============"); break; } } app/src/main/java/safeluck/drive/evaluation/im/MessageProcessor.java
@@ -2,9 +2,12 @@ import android.util.Log; import com.anyun.exam.lib.MyLog; import com.anyun.im_lib.util.ByteUtil; import safeluck.drive.evaluation.platformMessage.PlatFormConstant; import safeluck.drive.evaluation.platformMessage.RegisterResp; import safeluck.drive.evaluation.platformMessage.ServerCommonRsp; import safeluck.drive.evaluation.util.CThreadPoolExecutor; import safeluck.drive.evaluation.util.Utils; @@ -49,6 +52,13 @@ case (short) 0x8100: RegisterResp registerResp = new RegisterResp(datas); break; case (short) 0x8001://服务器端 通用应答 ServerCommonRsp serverCommonRsp = new ServerCommonRsp(datas); if (serverCommonRsp.getResult() == PlatFormConstant.SUCCESS){ MyLog.i(PlatFormConstant.TAG,"确认"+serverCommonRsp.getMsgId()+"消息成功"); } break; } } app/src/main/java/safeluck/drive/evaluation/platformMessage/JK2019MessageBase.java
New file @@ -0,0 +1,167 @@ package safeluck.drive.evaluation.platformMessage; import android.util.Log; import com.safeluck.aykj.annotation.AnnotationRegister; import com.safeluck.aykj.annotation.Int16; import com.safeluck.aykj.annotation.Int8; import com.safeluck.aykj.annotation.Length; import com.safeluck.aykj.annotation.Order; import com.safeluck.aykj.decoder.BitStateCoder; import com.safeluck.aykj.decoder.Int16Coder; import com.safeluck.aykj.message.BinMessageBase; import com.safeluck.aykj.utils.BitState; import com.safeluck.aykj.utils.BytesUtils; import safeluck.drive.evaluation.platformMessage.decoder.JWD; import safeluck.drive.evaluation.platformMessage.decoder.JWDCoder; import safeluck.drive.evaluation.platformMessage.decoder.Phone; import safeluck.drive.evaluation.platformMessage.decoder.PhoneCoder; public class JK2019MessageBase extends BinMessageBase { static { AnnotationRegister.register(JWD.class, new JWDCoder()); AnnotationRegister.register(Phone.class, new PhoneCoder()); } static Int16Coder coder = new Int16Coder(); public JK2019MessageBase() { this.messageNo = getMessageNo(); String message_name = this.getClass().getSimpleName(); if(message_name.startsWith("JTMessage")) { String message_id = message_name.substring(9,13); if(message_id.equals("Unkn") ){ return; } this.messageId= coder.decode(message_id); } this.setMultiPacket(false); this.registerDisableField("totalPacket"); this.registerDisableField("packetNo"); } @Override public void parse(String hex){ BitStateCoder coder = new BitStateCoder(); this.props = coder.decode(hex.substring(8,12)); if(this.isMultiPacket()) { this.removeDisableField("totalPacket"); this.removeDisableField("packetNo"); } super.parse(hex); } @Override public String toString() { if(!this.isMultiPacket()) { this.registerDisableField("totalPacket"); this.registerDisableField("packetNo"); } //计算消息体长度 String hex = super.toString(); Log.i(PlatFormConstant.TAG, "toString: 消息体长度:"+hex); int message_head_len = 19; if(this.isMultiPacket()) { message_head_len+=4; } // int len1 = this.getMessageLen(); int len2 = hex.length()/2-message_head_len; this.setMessageLen(len2); //计算校验 hex = super.toString(); byte[] bytes = BytesUtils.hexStringToBytes(hex); bytes[bytes.length - 2] = BytesUtils.xor(bytes,1,bytes.length -2); return BytesUtils.bytesToHexString(bytes); } @Order(1) @Int8 public int head=0x7E; @Order(2) @Int8 public int protocalVer=0x80; @Order(3) @Int16 public int messageId; @Order(4) @Length(2) @com.safeluck.aykj.annotation.BitState public BitState props = new BitState((byte) 0); @Order(5) @Phone public String phone; @Order(6) @Int16 public int messageNo; @Order(7) @Int8 public int reserved = 0; @Order(8) @Int16 public int totalPacket; @Order(9) @Int16 public int packetNo; @Order(Integer.MAX_VALUE-10001) @Int8 public int checksum; @Order(Integer.MAX_VALUE-10000) @Int8 public int end=0x7E; /** * 是否消息经过分包处理 * @param b */ public void setMultiPacket(boolean b) { this.props.set(13,b); } public boolean isMultiPacket() { return this.props.get(13); } /** * 获取属性中的消息体长度 * @return */ public int getMessageLen() { BitState state = new BitState((short)this.props.value); for (int i = 0; i < 10; i++) { state.set(10 + i, false); } return (int) state.value; } /** * 设置属性中的消息体长度 * @param len */ public void setMessageLen(int len) { BitState state = new BitState((short)len); for (int i = 0; i < 10; i++) { this.props.set(i, state.get(i)); } } } app/src/main/java/safeluck/drive/evaluation/platformMessage/JKClientCommonMessage.java
New file @@ -0,0 +1,26 @@ package safeluck.drive.evaluation.platformMessage; import com.safeluck.aykj.annotation.Hex; import com.safeluck.aykj.annotation.Int16; import com.safeluck.aykj.annotation.Int8; import com.safeluck.aykj.annotation.Length; import com.safeluck.aykj.annotation.Order; public class JKClientCommonMessage extends JK2019MessageBase { public static int SUCCESS=0; public static int FAIL=1; public static int ERROR_MSG=2; public static int NOT_SUPPORT=3; @Order(1) @Int16 public int respNo; @Order(2) @Length(2) @Hex public String respMessageId; @Order(3) @Int8 public int result; } app/src/main/java/safeluck/drive/evaluation/platformMessage/JKRegisterMessage.java
New file @@ -0,0 +1,31 @@ package safeluck.drive.evaluation.platformMessage; import com.safeluck.aykj.annotation.Ascii; import com.safeluck.aykj.annotation.Int16; import com.safeluck.aykj.annotation.Length; import com.safeluck.aykj.annotation.Order; public class JKRegisterMessage extends JK2019MessageBase { @Order(1) @Int16 public int proviceid; @Order(2) @Int16 public int cityid; @Order(3) @Length(20) @Ascii public String model; @Order(4) @Length(16) @Ascii public String sn; @Order(5) @Length(15) @Ascii public String imei; } app/src/main/java/safeluck/drive/evaluation/platformMessage/ServerCommonRsp.java
@@ -49,4 +49,12 @@ public short getResult() { return result; } public short getMsgId() { return msgId; } public short getMsg_serial_num() { return msg_serial_num; } } app/src/main/java/safeluck/drive/evaluation/platformMessage/decoder/JWD.java
New file @@ -0,0 +1,19 @@ package safeluck.drive.evaluation.platformMessage.decoder; import com.safeluck.aykj.annotation.Length; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zw on 2017/6/15. */ @Length(4) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface JWD { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } app/src/main/java/safeluck/drive/evaluation/platformMessage/decoder/JWDCoder.java
New file @@ -0,0 +1,29 @@ package safeluck.drive.evaluation.platformMessage.decoder; import com.safeluck.aykj.decoder.BaseDecoder; import com.safeluck.aykj.decoder.Int32Coder; import java.math.BigDecimal; import java.util.Date; /** * Created by zw on 2017/6/15. */ public class JWDCoder extends BaseDecoder<Double> { Int32Coder coder = new Int32Coder(); @Override public Double decode(String str) { double ret = coder.decode(str); double x = ret / 1000000; BigDecimal bg = new BigDecimal(x); double f1 = bg.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue(); return f1; } @Override public String encode(Double str) { int jwd = (int)(str * 1000000); return coder.encode(jwd); } } app/src/main/java/safeluck/drive/evaluation/platformMessage/decoder/Param0104.java
New file @@ -0,0 +1,14 @@ package safeluck.drive.evaluation.platformMessage.decoder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by shiyu on 2016/12/28. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Param0104 { } app/src/main/java/safeluck/drive/evaluation/platformMessage/decoder/Param8103.java
New file @@ -0,0 +1,14 @@ package safeluck.drive.evaluation.platformMessage.decoder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by shiyu on 2016/12/28. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Param8103 { } app/src/main/java/safeluck/drive/evaluation/platformMessage/decoder/Phone.java
New file @@ -0,0 +1,19 @@ package safeluck.drive.evaluation.platformMessage.decoder; import com.safeluck.aykj.annotation.Length; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zw on 2017/6/15. */ @Length(8) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Phone { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } app/src/main/java/safeluck/drive/evaluation/platformMessage/decoder/PhoneCoder.java
New file @@ -0,0 +1,29 @@ package safeluck.drive.evaluation.platformMessage.decoder; import android.util.Log; import com.anyun.im_lib.util.ByteUtil; import com.safeluck.aykj.decoder.BaseDecoder; import com.safeluck.aykj.utils.BytesUtils; public class PhoneCoder extends BaseDecoder<String> { private static final String TAG = "PhoneCoder"; @Override public String decode(String str) { return str.substring(8); } @Override public String encode(String str) { Log.i(TAG, "encode: "+str); if(str==null||"".equalsIgnoreCase(str)) { // str ="00000000000"; str ="0000000000000000"; } byte[] bcdBytes = ByteUtil.str2Bcd(str); // return "00000"+str; return BytesUtils.bytesToHexString(bcdBytes); } } app/src/main/java/safeluck/drive/evaluation/platformMessage/utils/MessageEscaper.java
New file @@ -0,0 +1,85 @@ package safeluck.drive.evaluation.platformMessage.utils; import com.safeluck.aykj.utils.ArrayUtils; /** * Created by zw on 2017/7/8. * 蓝牙协议转义 */ public class MessageEscaper { public byte[] escape(byte[] source_bytes) { byte[] return_bytes = new byte[source_bytes.length*2]; int size = source_bytes.length; int pos = 0; for (int i = 0; i < size; i++) { if (i == 0||i==size-1) { return_bytes[pos++] = source_bytes[i]; continue; } if (source_bytes[i] == 0x7d) { return_bytes[pos++] = 0x7d; return_bytes[pos++] = 0x01; } else if (source_bytes[i] == 0x7e) { return_bytes[pos++] = 0x7d; return_bytes[pos++] = 0x02; } else { return_bytes[pos++] = source_bytes[i]; } } return ArrayUtils.subArray(return_bytes,0,pos); } public byte[] unescape(byte[] cmd_bytes) { //转义还原 int len = cmd_bytes.length; byte[] return_bytes = new byte[cmd_bytes.length]; //int len = ByteHelper.HexString2Byte(cmd, cmd_bytes); int pos = 0; for (int i = 0; i < len; i++) { if (i == len - 1) { return_bytes[pos++] = cmd_bytes[i]; continue; } if (cmd_bytes[i] == 0x7d && cmd_bytes[i + 1] == 0x02) { return_bytes[pos++] = 0x7e; i++; continue; } else if (cmd_bytes[i] == 0x7d && cmd_bytes[i + 1] == 0x01) { return_bytes[pos++] = 0x7d; i++; continue; } else { return_bytes[pos++] = cmd_bytes[i]; } } return ArrayUtils.subArray(return_bytes,0,pos); } } app/src/main/java/safeluck/drive/evaluation/platformMessage/utils/MessageManager.java
New file @@ -0,0 +1,63 @@ //package safeluck.drive.evaluation.platformMessage.utils; // //import com.safeluck.aykj.decoder.BitStateCoder; //import com.safeluck.aykj.decoder.Int16Coder; //import com.safeluck.aykj.utils.BitState; // //import safeluck.drive.evaluation.platformMessage.JK2019MessageBase; // ///** // * Created by zhouwei on 2016/12/7. // */ // //public final class MessageManager { // // public static JK2019MessageBase get(String cmd) { // String head = cmd.substring(4,8); // String classname = "aykj.message.jt808_2016.server.JTMessage"+head; // if("0900".equals(head)||"8900".equals(head)) // classname = "aykj.message.jt808_2016.JTMessage"+head; // Class c = null; // try { // c = Class.forName(classname); // } catch (ClassNotFoundException e) { // classname = "aykj.message.jt808_2016.device.JTMessage"+head; // try { // c = Class.forName(classname); // } catch (ClassNotFoundException e1) { //// c = JTMessageUnknown.class; // } // } // try { // // JK2019MessageBase ret = (JK2019MessageBase)c.newInstance(); // ret.parse(cmd); // if(ret.messageId==0x8900||ret.messageId==0x0900){ //// JTMessageExtend ext = (JTMessageExtend)ret; // if(ret.messageId==0x8900) //// classname = "aykj.message.jt808_2016.server.ExtendMessage"+ String.format("%04X", ext.extend_id); // else //// classname = "aykj.message.jt808_2016.device.ExtendMessage"+ String.format("%04X", ext.extend_id); // try { // c = Class.forName(classname); // } catch (ClassNotFoundException e) { // classname = "aykj.message.jt808_2016.device.JTMessage"+head; // try { // c = Class.forName(classname); // } catch (ClassNotFoundException e1) { //// c = JTMessageUnknown.class; // } // } // // JK2019MessageBase ext_ret = (JK2019MessageBase)c.newInstance(); // ext_ret.parse(cmd); // ret = ext_ret; // } // return ret; // } catch (InstantiationException e) { // throw new RuntimeException(e); // } catch (IllegalAccessException e) { // throw new RuntimeException(e); // } // } //} im_lib/src/main/java/com/anyun/im_lib/netty/NettyTcpClient.java
@@ -12,6 +12,7 @@ import com.anyun.im_lib.listener.IMSConnectStatusCallback; import com.anyun.im_lib.listener.OnEventListener; import com.anyun.im_lib.util.ByteUtil; import com.safeluck.aykj.utils.BytesUtils; import java.nio.ByteBuffer; import java.util.Vector; @@ -218,14 +219,14 @@ imsConnectStatusCallback.onConnected(); } // TODO: 2019/12/12 连接成功 ,发送握手消息(需要的话——) try { ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer(); byteBuf.writeBytes(mOnEventListener.getRegisterMessage()); Log.i(TAG, "发送消息: "+ ByteUtil.byte2HexStr(mOnEventListener.getRegisterMessage())); channel.writeAndFlush(byteBuf); } catch (Exception e) { Log.i(TAG, "发送消息失败,reason="+e.getMessage()+"\t"); } // try { // ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer(); // byteBuf.writeBytes(mOnEventListener.getRegisterMessage()); // Log.i(TAG, "发送消息: "+ ByteUtil.byte2HexStr(mOnEventListener.getRegisterMessage())); // channel.writeAndFlush(byteBuf); // } catch (Exception e) { // Log.i(TAG, "发送消息失败,reason="+e.getMessage()+"\t"); // } break; case IMSConfig.CONNECT_STATE_FAILURE: default: @@ -331,6 +332,7 @@ Log.i(TAG, "sendMsg fail,channel为空"+msg); } try { Log.i(TAG, "sendMsg: "+ BytesUtils.bytesToHexString(msg)); ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer(); byteBuf.writeBytes(msg); channel.writeAndFlush(byteBuf); im_lib/src/main/java/com/safeluck/aykj/annotation/AnnotationRegister.java
New file @@ -0,0 +1,58 @@ package com.safeluck.aykj.annotation; import com.safeluck.aykj.decoder.*; import java.lang.reflect.Field; import java.util.HashMap; /** * Created by zhouwei on 2016/12/1. */ public final class AnnotationRegister { static HashMap hashMap = new HashMap(); static { register(Int16.class,new Int16Coder()); register(Int32.class,new Int32Coder()); register(Int8.class,new ByteCoder()); register(GBK.class,new GBKStringDecoder()); register(Ascii.class,new GBKStringDecoder()); register(BitState.class,new BitStateCoder()); register(Hex.class,new DefaultHexCoder()); register(UTF8.class,new UTF8StringDecoder()); register(Bytes.class,new BytesCoder()); register(Message.class,new BinMessageCoder()); register(BcdDate.class,new BcdDateCoder()); register(BcdDateTime.class,new BcdDateTimeCoder()); register(Int16LE.class,new Int16LECoder()); register(Int32LE.class,new Int32LECoder()); } public static void register(Class annotation, IMessageCoder<?> coder) { hashMap.put(annotation,coder); } public static IMessageCoder getCoder(Class annotation) { IMessageCoder decoder = (IMessageCoder)hashMap.get(annotation); if(decoder instanceof BaseDecoder) { BaseDecoder baseDecoder = (BaseDecoder)decoder; if(!baseDecoder.isSingleton) { try { decoder = decoder.getClass().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } } return decoder; } } im_lib/src/main/java/com/safeluck/aykj/annotation/Ascii.java
New file @@ -0,0 +1,14 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Ascii { } im_lib/src/main/java/com/safeluck/aykj/annotation/BcdDate.java
New file @@ -0,0 +1,16 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zw on 2017/6/15. */ @Length(3) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface BcdDate { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/BcdDateTime.java
New file @@ -0,0 +1,16 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zw on 2017/6/15. */ @Length(6) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface BcdDateTime { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/BitState.java
New file @@ -0,0 +1,15 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface BitState { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/Bytes.java
New file @@ -0,0 +1,14 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Bytes { } im_lib/src/main/java/com/safeluck/aykj/annotation/FromEnd.java
New file @@ -0,0 +1,17 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zw on 2017/7/11. * 从结尾开始解析而不是从开头 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface FromEnd { int value(); } im_lib/src/main/java/com/safeluck/aykj/annotation/GBK.java
New file @@ -0,0 +1,15 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface GBK { } im_lib/src/main/java/com/safeluck/aykj/annotation/Hex.java
New file @@ -0,0 +1,14 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Hex { } im_lib/src/main/java/com/safeluck/aykj/annotation/Int16.java
New file @@ -0,0 +1,20 @@ package com.safeluck.aykj.annotation; import com.safeluck.aykj.decoder.IMessageCoder; import com.safeluck.aykj.decoder.Int16Coder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Length(2) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Int16 { // Class<? extends IMessageCoder<?>>[] coder() default Int16Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/Int16LE.java
New file @@ -0,0 +1,18 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. * 小端模式 低位在前 */ @Length(2) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Int16LE { // Class<? extends IMessageCoder<?>>[] coder() default Int16Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/Int32.java
New file @@ -0,0 +1,20 @@ package com.safeluck.aykj.annotation; import com.safeluck.aykj.decoder.IMessageCoder; import com.safeluck.aykj.decoder.Int16Coder; import com.safeluck.aykj.decoder.Int32Coder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Length(4) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Int32 { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/Int32LE.java
New file @@ -0,0 +1,17 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. * 小端模式 低位在前 */ @Length(4) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Int32LE { // Class<? extends IMessageCoder<?>>[] coder() default Int32Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/Int8.java
New file @@ -0,0 +1,16 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Length(1) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Int8 { // Class<? extends IMessageCoder<?>>[] coder() default Int16Coder.class; } im_lib/src/main/java/com/safeluck/aykj/annotation/Length.java
New file @@ -0,0 +1,34 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Length { int value() default 0; String lengthField() default ""; /** * 如果长度不足的填充方向 * @return */ PaddingWay paddingWay() default PaddingWay.RIGHT; /** * 长度不足的填充字符 * @return */ byte paddingByte() default 0x00; enum PaddingWay { LEFT,RIGHT; } } im_lib/src/main/java/com/safeluck/aykj/annotation/Message.java
New file @@ -0,0 +1,15 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface Message { } im_lib/src/main/java/com/safeluck/aykj/annotation/Order.java
New file @@ -0,0 +1,15 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Order { int value() default -1; } im_lib/src/main/java/com/safeluck/aykj/annotation/UTF8.java
New file @@ -0,0 +1,14 @@ package com.safeluck.aykj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by zhouwei on 2016/12/1. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.TYPE}) public @interface UTF8 { } im_lib/src/main/java/com/safeluck/aykj/decoder/BCDCoder.java
New file @@ -0,0 +1,18 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ //public class BCDCoder implements IMessageCoder<String> { // @Override // public String decode(String str) { // return Integer.valueOf(str, 16).intValue(); // } // // @Override // public String encode(String i) { // return BytesUtils.toHexString(i.byteValue()); // } //} im_lib/src/main/java/com/safeluck/aykj/decoder/BaseDecoder.java
New file @@ -0,0 +1,23 @@ package com.safeluck.aykj.decoder; /** * Created by zhouwei on 2016/12/20. */ public abstract class BaseDecoder<T> implements IMessageCoder<T> { public boolean isSingleton = true; protected Class<? extends T> fieldClass; @Override public Class<? extends T> getFieldClass() { return fieldClass; } @Override public void setFieldClass(Class<? extends T> value) { fieldClass =value; } } im_lib/src/main/java/com/safeluck/aykj/decoder/BcdDateCoder.java
New file @@ -0,0 +1,28 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BitState; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by zw on 2017/6/15. */ public class BcdDateCoder extends BaseDecoder<Date> { SimpleDateFormat f= new SimpleDateFormat("yyMMdd"); @Override public Date decode(String date) { try { return f.parse(date); } catch (ParseException e) { throw new RuntimeException(e); } } @Override public String encode(Date date) { return f.format(date); } } im_lib/src/main/java/com/safeluck/aykj/decoder/BcdDateTimeCoder.java
New file @@ -0,0 +1,26 @@ package com.safeluck.aykj.decoder; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by zw on 2017/6/15. */ public class BcdDateTimeCoder extends BaseDecoder<Date> { SimpleDateFormat f= new SimpleDateFormat("yyMMddHHmmss"); @Override public Date decode(String date) { try { return f.parse(date); } catch (ParseException e) { throw new RuntimeException(e); } } @Override public String encode(Date date) { return f.format(date); } } im_lib/src/main/java/com/safeluck/aykj/decoder/BinMessageCoder.java
New file @@ -0,0 +1,30 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.message.BinMessageBase; /** * Created by zhouwei on 2016/12/1. */ public class BinMessageCoder extends BaseDecoder<BinMessageBase> { public BinMessageCoder() { this.isSingleton = false; } @Override public BinMessageBase decode(String str) { try { BinMessageBase messageBase = this.fieldClass.newInstance(); messageBase.parse(str); return messageBase; } catch (Exception ex) { throw new RuntimeException(ex); } } @Override public String encode(BinMessageBase i) { return i.toString(); } } im_lib/src/main/java/com/safeluck/aykj/decoder/BitStateCoder.java
New file @@ -0,0 +1,45 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BitState; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class BitStateCoder extends BaseDecoder<BitState> { Int16Coder int16Coder = new Int16Coder(); Int32Coder int32Coder = new Int32Coder(); @Override public BitState decode(String str) { if(str.length()==2) { return new BitState(Byte.valueOf(str,16)); } if(str.length()==4) { return new BitState(Short.valueOf(str,16)); } if(str.length()==8) { return new BitState(Integer.valueOf(str,16)); } throw new RuntimeException("BitState长度不对,数据="+str); } @Override public String encode(BitState i) { if(i.total==8) { return BytesUtils.toHexString((byte)i.value); } if(i.total==16) { return int16Coder.encode((int)i.value); } if(i.total==32) { return int32Coder.encode((int)i.value); } throw new RuntimeException("BitState长度不对,数据="+i.total); } } im_lib/src/main/java/com/safeluck/aykj/decoder/ByteCoder.java
New file @@ -0,0 +1,24 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class ByteCoder extends BaseDecoder<Integer> { public static ByteCoder instance = new ByteCoder(); @Override public Integer decode(String str) { if(str==null||"".equals(str)) return 0; return Integer.valueOf(str, 16).intValue(); } @Override public String encode(Integer i) { if(i==null) i=0; return BytesUtils.toHexString(i.byteValue()); } } im_lib/src/main/java/com/safeluck/aykj/decoder/BytesCoder.java
New file @@ -0,0 +1,19 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class BytesCoder extends BaseDecoder<Object> { @Override public Object decode(String str) { return BytesUtils.hexStringToBytes(str); } @Override public String encode(Object i) { byte[] bytes = (byte[])i; return BytesUtils.bytesToHexString(bytes); } } im_lib/src/main/java/com/safeluck/aykj/decoder/DefaultHexCoder.java
New file @@ -0,0 +1,18 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class DefaultHexCoder extends BaseDecoder<String> { @Override public String decode(String str) { return str; } @Override public String encode(String i) { return i; } } im_lib/src/main/java/com/safeluck/aykj/decoder/GBKStringDecoder.java
New file @@ -0,0 +1,63 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; import java.io.UnsupportedEncodingException; /** * Created by zhouwei on 2016/12/3. */ public class GBKStringDecoder extends BaseDecoder<String> { public String stripEnd(String str, String stripChars) { int end; if(str != null && (end = str.length()) != 0) { if(stripChars == null) { while(end != 0 && Character.isWhitespace(str.charAt(end - 1))) { --end; } } else { if(stripChars.length() == 0) { return str; } while(end != 0 && stripChars.indexOf(str.charAt(end - 1)) != -1) { --end; } } return str.substring(0, end); } else { return str; } } @Override public String decode(String str) { if(str==null) return null; byte[] bytes = BytesUtils.hexStringToBytes(str); try { String ret = new String(bytes,"gbk").trim(); return ret;// this.stripEnd(ret,"\0"); } catch (UnsupportedEncodingException e) { return null; } } @Override public String encode(String str) { try { if(str==null) return null; return BytesUtils.bytesToHexString(str.getBytes("gbk")); } catch (UnsupportedEncodingException e) { return null; } } } im_lib/src/main/java/com/safeluck/aykj/decoder/IMessageCoder.java
New file @@ -0,0 +1,13 @@ package com.safeluck.aykj.decoder; /** * Created by zhouwei on 2016/12/1. */ public interface IMessageCoder<T> { T decode(String str); String encode(T str); Class<? extends T> getFieldClass(); void setFieldClass(Class<? extends T> value); } im_lib/src/main/java/com/safeluck/aykj/decoder/Int16Coder.java
New file @@ -0,0 +1,29 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.annotation.Int16; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class Int16Coder extends BaseDecoder<Integer> { public static Int16Coder instance = new Int16Coder(); @Override public Integer decode(String str) { if(str==null||"".equals(str)) return 0; return Integer.valueOf(str, 16); } @Override public String encode(Integer i) { if(i==null) i=0; byte[] b = new byte[2]; b[1]= (byte)(i&0xff); b[0]= (byte)(i >> 8); return BytesUtils.bytesToHexString(b); } } im_lib/src/main/java/com/safeluck/aykj/decoder/Int16LECoder.java
New file @@ -0,0 +1,42 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class Int16LECoder extends BaseDecoder<Integer> { public static Int16LECoder instance = new Int16LECoder(); @Override public Integer decode(String str) { byte[] src = BytesUtils.hexStringToBytes(str); int offset = 0; int value; value = (src[offset] & 0xFF) | ((src[offset + 1] & 0xFF) << 8); // | ((src[offset + 2] & 0xFF) << 16) // | ((src[offset + 3] & 0xFF) << 24)); return value; // return Integer.valueOf(Short.reverseBytes(Int16Coder.instance.decode(str).shortValue())&0xFF); // if(str==null||"".equals(str)) // return 0; // // return Integer.valueOf(str, 16); } @Override public String encode(Integer i) { if(i==null) i=0; int value = i.intValue(); byte[] src = new byte[2]; // src[3] = (byte) ((value >> 24) & 0xFF); // src[2] = (byte) ((value >> 16) & 0xFF); src[1] = (byte) ((value >> 8) & 0xFF); src[0] = (byte) (value & 0xFF); return BytesUtils.bytesToHexString(src); } } im_lib/src/main/java/com/safeluck/aykj/decoder/Int32Coder.java
New file @@ -0,0 +1,33 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.annotation.Int32; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class Int32Coder extends BaseDecoder<Integer> { public static Int32Coder instance = new Int32Coder(); @Override public Integer decode(String str) { if(str==null||"".equals(str)) return 0; return Integer.valueOf(str, 16); } @Override public String encode(Integer i) { if(i==null) i=0; //高位在前 32位整数 int num = i.intValue(); byte[] b = new byte[4]; b[3]= (byte)(num&0xff); b[2]= (byte)(num >> 8); b[1]= (byte)(num >> 16); b[0]= (byte)(num >> 24); return BytesUtils.bytesToHexString(b); } } im_lib/src/main/java/com/safeluck/aykj/decoder/Int32LECoder.java
New file @@ -0,0 +1,39 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; /** * Created by zhouwei on 2016/12/1. */ public class Int32LECoder extends BaseDecoder<Integer> { public static Int32LECoder instance = new Int32LECoder(); @Override public Integer decode(String str) { return Integer.reverseBytes(Int32Coder.instance.decode(str)); // byte[] src = BytesUtils.hexStringToBytes(str); // int offset = 0; // int value; // value = (int) ((src[offset] & 0xFF) // | ((src[offset + 1] & 0xFF) << 8) // | ((src[offset + 2] & 0xFF) << 16) // | ((src[offset + 3] & 0xFF) << 24)); // return value; } //低位在前 32位整数 @Override public String encode(Integer i) { return Int32Coder.instance.encode(Integer.reverseBytes(i)); // if(i==null) // i=0; // int value = i.intValue(); // byte[] src = new byte[4]; // src[3] = (byte) ((value >> 24) & 0xFF); // src[2] = (byte) ((value >> 16) & 0xFF); // src[1] = (byte) ((value >> 8) & 0xFF); // src[0] = (byte) (value & 0xFF); // return BytesUtils.bytesToHexString(src); } } im_lib/src/main/java/com/safeluck/aykj/decoder/UTF8StringDecoder.java
New file @@ -0,0 +1,37 @@ package com.safeluck.aykj.decoder; import com.safeluck.aykj.utils.BytesUtils; import java.io.UnsupportedEncodingException; /** * Created by zhouwei on 2016/12/3. */ public class UTF8StringDecoder extends BaseDecoder<String> { @Override public String decode(String str) { if(str==null) return null; byte[] bytes = BytesUtils.hexStringToBytes(str); try { return new String(bytes,"utf-8"); } catch (UnsupportedEncodingException e) { return null; } } @Override public String encode(String str) { try { if(str==null) return null; return BytesUtils.bytesToHexString(str.getBytes("utf-8")); } catch (UnsupportedEncodingException e) { return null; } } } im_lib/src/main/java/com/safeluck/aykj/message/BinMessageBase.java
New file @@ -0,0 +1,397 @@ package com.safeluck.aykj.message; import android.util.Log; import com.safeluck.aykj.annotation.AnnotationRegister; import com.safeluck.aykj.annotation.FromEnd; import com.safeluck.aykj.annotation.Length; import com.safeluck.aykj.annotation.Order; import com.safeluck.aykj.decoder.IMessageCoder; import com.safeluck.aykj.utils.BytesUtils; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import io.netty.util.internal.PlatformDependent; @SuppressWarnings("Since15") public class BinMessageBase { static short m_messageNo; protected synchronized short getMessageNo() { m_messageNo++; if(m_messageNo>=Short.MAX_VALUE-1) { m_messageNo = 0; } return m_messageNo; } static HashMap<Class,FieldDefine[]> fieldDefines = new HashMap<>(); protected List<String> disabledFields = new ArrayList<>(); public void parse(String hex) { try { FieldDefine[] fields = this.getFieldDefines(); int total = hex.length(); int used = 0; int dynamic_len_field_count = 0; int relative_len_field_count = 0; //如果有为动态长度的,计算出长度 for (FieldDefine fieldDefine : fields) { if (this.disabledFields.contains(fieldDefine.field.getName())) { continue; } //计算依赖长度字段数量 if (fieldDefine.relativeLengthField != null) { relative_len_field_count++; } if (fieldDefine.relativeLengthField == null && fieldDefine.getFieldLen() == 0) { dynamic_len_field_count++; } //动态长度,去掉其他所有字段的长度,剩余的为此字段长度 if (fieldDefine.getFieldLen() > 0) { System.out.println(fieldDefine.field.getName() + "长度=" + fieldDefine.getFieldLen() * 2); used += (fieldDefine.getFieldLen() * 2); } } if (dynamic_len_field_count > 1) { buildException("动态长度字段只能有一个"); } if (dynamic_len_field_count > 0 && relative_len_field_count > 0) { buildException("动态长度字段和依赖长度字段只能有一个"); } int dynamic_len = (total - used); int start = 0; for (FieldDefine fieldDefine : fields) { if (this.disabledFields.contains(fieldDefine.field.getName())) { continue; } //解析依赖长度 if (fieldDefine.relativeLengthField != null) { try { Field lengthField = this.getClass().getField(fieldDefine.length.lengthField()); int len = (int) lengthField.get(this); System.out.println(fieldDefine.field.getName() + ":依赖长度=" + len); fieldDefine.setFieldLen(len); ; } catch (Exception e) { buildException(e.getMessage()); } } int str_hex_len = fieldDefine.getFieldLen() * 2; if (str_hex_len <= 0) { str_hex_len = dynamic_len; } String field_hex = null; Object value = null; if (fieldDefine.from_end_index >= 0) { field_hex = hex.substring(hex.length() - str_hex_len - fieldDefine.from_end_index, hex.length() - fieldDefine.from_end_index); value = fieldDefine.coder.decode(field_hex); } else { field_hex = hex.substring(start, start + str_hex_len); start += str_hex_len; value = fieldDefine.coder.decode(field_hex); } try { fieldDefine.field.set(this, value); // Object val = fieldDefine.field.get(this); // System.out.println(fieldDefine.field.getName()+":get="+val); } catch (IllegalAccessException e) { this.buildException(e.getMessage()); } } } catch (ParseException ex) { throw ex; } catch (Exception ex) { this.buildException(ex.getMessage()); } } public void registerDisableField(String field) { if(!this.disabledFields.contains(field)) { this.disabledFields.add(field); } } public void removeDisableField(String field) { this.disabledFields.remove(field); } protected void buildException(String error) { throw new ParseException(error,this); } public byte[] toBytes() { String hex = this.toString(); return BytesUtils.hexStringToBytes(hex); } @Override public String toString() { StringBuilder sb = new StringBuilder(); FieldDefine[] fields = this.getFieldDefines(); //写动态长度字段长度 for (FieldDefine fieldDefine:fields) { if (this.disabledFields.contains(fieldDefine.field.getName())) { continue; } Log.i("PlatFormMessage", "1field: "+fieldDefine.field.getName()); if(fieldDefine.relativeLengthField==null) continue; try { Object value = fieldDefine.field.get(this); String hex = fieldDefine.coder.encode(value); if (hex == null) { fieldDefine.relativeLengthField.set(this, 0); } else { fieldDefine.relativeLengthField.set(this, hex.length() / 2); } } catch(IllegalAccessException e) { this.buildException(e.getMessage()); } } for (FieldDefine fieldDefine:fields) { if(this.disabledFields.contains(fieldDefine.field.getName())) { continue; } Log.i("PlatFormMessage", "2field: "+fieldDefine.field.getName()); try { Object obj = fieldDefine.field.get(this); String hex = fieldDefine.coder.encode(obj); if(hex==null) { hex = ""; } if (fieldDefine.field.getName().equalsIgnoreCase("phone")){ Log.i("PlatFormMessage", "phone toString: "+hex ); } int defineLen = fieldDefine.getFieldLen(); if(hex.length()>defineLen*2&&defineLen>0) { this.buildException("字段"+fieldDefine.field.getName()+"长度超过限制"); } if(hex.length()<defineLen*2&&defineLen>0) { if(fieldDefine.length.paddingWay()== Length.PaddingWay.RIGHT) { hex = this.getPaddingRightString(hex,fieldDefine.getFieldLen()*2, BytesUtils.toHexString(fieldDefine.length.paddingByte())); } else { hex = this.getPaddingLeftString(hex,fieldDefine.getFieldLen()*2, BytesUtils.toHexString(fieldDefine.length.paddingByte())); } } // System.out.println(hex); sb.append(hex); } catch (IllegalAccessException e) { this.buildException(e.getMessage()); } } return sb.toString(); } String getPaddingLeftString(String str, int total_len,String padding) { while (str.length() < total_len) { str = padding + str; } return str; } String getPaddingRightString(String str, int total_len,String padding) { while (str.length() < total_len) { str = str+padding; } return str; } public synchronized FieldDefine[] getFieldDefines() { if(!fieldDefines.containsKey(this.getClass())) { Field[] fields = this.getClass().getFields(); List<FieldDefine> fieldDefineList = new ArrayList<>(); // int sort = 0; List<Class> baseClassList = new ArrayList<>(); for (Field field:fields) { if(Modifier.isStatic(field.getModifiers())) continue; if(Modifier.isPrivate(field.getModifiers())) continue; if(field.getAnnotation(Order.class)==null) continue; FieldDefine fieldDefine = new FieldDefine(field); if(fieldDefine.coder!=null) { fieldDefineList.add(fieldDefine); if(baseClassList.indexOf(field.getDeclaringClass())<0) { baseClassList.add(field.getDeclaringClass()); } } if(fieldDefine.length.lengthField()!=null&&!"".equals(fieldDefine.length.lengthField())) { try { fieldDefine.relativeLengthField = this.getClass().getField(fieldDefine.length.lengthField()); } catch (NoSuchFieldException e) { this.buildException(e.getMessage()); } } } //排序出基类 Collections.sort(baseClassList,new Comparator<Class>() { @Override public int compare(Class c1, Class c2) { if(c2.isAssignableFrom(c1)) { return 1; } return -1; } }); //重新排序 int sort = 0; for(Class c:baseClassList) { sort+=100; for(FieldDefine fieldDefine:fieldDefineList) { if(fieldDefine.field.getDeclaringClass().equals(c))//&&fieldDefine.order==0) { if(fieldDefine.order+sort>0) { fieldDefine.order += sort; } } } } Collections.sort(fieldDefineList,new Comparator<FieldDefine>() { @Override public int compare(FieldDefine t0, FieldDefine t1) { int order0 = t0.order;//+(pos0+1); int order1 = t1.order;//+(pos1+1); if(order0>order1) return 1; if(order0==order1) return 0; return -1; } }); fieldDefines.put(this.getClass(),fieldDefineList.toArray(new FieldDefine[0])); } FieldDefine[] result = fieldDefines.get(this.getClass()); for(FieldDefine fieldDefine:result) { fieldDefine.setFieldLen(0); } return result; } class FieldDefine { public FieldDefine(Field field) { Annotation[] annotations = field.getAnnotations(); for (Annotation annotation:annotations) { IMessageCoder decoder = AnnotationRegister.getCoder(annotation.annotationType()); if(decoder!=null) { decoder.setFieldClass(field.getType()); coder = decoder; this.length = annotation.annotationType().getAnnotation(Length.class); break; } } this.field = field; if(this.length==null) { this.length = field.getAnnotation(Length.class); } if(this.length==null) { buildException(field.getName()+"未定义长度"); } Order orderAnnotation = field.getAnnotation(Order.class); if(orderAnnotation!=null) { this.order = orderAnnotation.value(); } FromEnd fromEnd = field.getAnnotation(FromEnd.class); if(fromEnd!=null) { from_end_index = fromEnd.value(); } } public Field relativeLengthField; public IMessageCoder coder; public Length length; public Field field; public int order; public int from_end_index = -1; private int field_len; public int getFieldLen() { if(this.length.value()>0) return this.length.value(); return field_len; } public void setFieldLen(int len) { this.field_len = len; } @Override public String toString() { return this.field.toString(); } } public String getDescription() { return this.toString(); } } im_lib/src/main/java/com/safeluck/aykj/message/ParseException.java
New file @@ -0,0 +1,15 @@ package com.safeluck.aykj.message; /** * Created by zhouwei on 2016/12/3. */ public class ParseException extends RuntimeException { public ParseException(String error,BinMessageBase message) { super(error); this.message = message; } public BinMessageBase message; } im_lib/src/main/java/com/safeluck/aykj/utils/ArrayUtils.java
New file @@ -0,0 +1,15 @@ package com.safeluck.aykj.utils; import android.util.Log; import static com.anyun.im_lib.util.ByteUtil.byte2HexStr; public class ArrayUtils { public static byte[] subArray(byte[] srcBytes, int begin, int length) { byte[] bytes = new byte[length]; System.arraycopy(srcBytes,begin,bytes,0,length); Log.i("ArrayUtils", "subArray: "+byte2HexStr(bytes)); return bytes; } } im_lib/src/main/java/com/safeluck/aykj/utils/BitState.java
New file @@ -0,0 +1,56 @@ package com.safeluck.aykj.utils; public class BitState { public BitState(int b) { this.value = b; this.total = 32; } public BitState(byte b) { this.value = b; this.total = 8; } public BitState(short b) { this.value = b; this.total = 16; } public int total = 32; public int value; public boolean get(int bit) { int pos = bit;//32 - bit; return (this.value >> pos & 1) == 1; } public void set(int pos, boolean state) { //11000110 int move_pos = pos;// 32 - pos; if (state) { this.value = this.value | 1 << move_pos; } else { this.value = this.value & ~(1 << move_pos); } } @Override public String toString() { String str = Integer.toBinaryString(this.value); return getPaddingRightString(str, this.total,"00"); } String getPaddingRightString(String str, int total_len,String padding) { while (str.length() < total_len) { str = str+padding; } return str; } } im_lib/src/main/java/com/safeluck/aykj/utils/BytesUtils.java
New file @@ -0,0 +1,110 @@ package com.safeluck.aykj.utils; public final class BytesUtils { public static String bytesToHexString(byte[] src,int len){ return bytesToHexString(src,0,len); } public static String bytesToHexString(byte[] src){ return bytesToHexString(src,0,src.length); } public static String bytesToHexString(byte[] src,int start,int len){ StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = start; i < len; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString().toUpperCase(); } public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } public static byte xor(byte[] bytes,int start,int end) { if (bytes.length < end) { throw new RuntimeException("计算xor的时候size不足"); } int s1 = bytes[start]; for (int i = start + 1; i < end; i++) { s1 = s1 ^ bytes[i]; } return (byte)s1; } public static byte xor(byte[] bytes) { return xor(bytes,0,bytes.length); } public static String toHexString(byte b) { String hex = Integer.toHexString(b&0xff).toUpperCase(); if(hex.length()==1) { return "0"+hex; } return hex; } public static int sum(byte[] bytes,int start,int end) { if (bytes.length < end) { throw new RuntimeException("计算sum的时候size不足"); } int s1 = 0; for (int i = start; i < end; i++) { // System.out.println(bytes[i]&0xFF); s1 += (bytes[i]&0xFF); // System.out.println("sum="+s1); } return s1; // int sum = 0; // for(byte b:bytes) // { // sum+=b; // } // return sum; } public static int sum(byte[] bytes) { return sum(bytes,0,bytes.length); } public static int getInt32(byte[] bytes,int start){ int result = 0; int a = (bytes[0+start] & 0xff) << 24; int b = (bytes[1+start] & 0xff) << 16; int c = (bytes[2+start] & 0xff) << 8; int d = (bytes[3+start] & 0xff); result = a | b | c | d; return result; } }