It has been a year since I started working. Looking back on the process, agreements account for the vast majority.
JSON (common communication text), protoBuf (the editor has written a tutorial), custom protocols (byte splicing, in some IoT fields the standards are almost all byte splicing), of course there are many others, but I don’t know how, and I still need to complete the agreement through asn (I haven’t been exposed to it)
For JSON and protoBuf, it is relatively simple, because there are ready-made libraries that call the JSON and protoBuf compilers;
For byte splicing, it may be more complicated, or it is not complicated at first, but the protocol is complicated, and the splicing becomes complicated;
The protocol in the form of splicing bytes also involves the big-endian and little-endian modes (the big-endian mode is that the low-order bytes are arranged at the low address end of the memory, and the high-order bytes are arranged at the high address end of the memory; while the little-endian mode is that the high-order words are The bits are placed at the low address end of the memory, and the low bytes are placed at the high address end of the memory)
A simple explanation is: big endian converts a number directly into a bytes array; while little endian requires a reverse inversion of the array;
Suppose there is such a protocol: (big end is used as an example below)
Protocol header:
Message name | Number of bytes occupied |
---|---|
Message header | 1 |
Message type | 1 |
Message version | 1 |
Message timestamp | 8 |
Message body | 1 + 15*n |
Agreement:
Message name | Number of bytes occupied |
---|---|
Number of perceived objects | 1 |
Perceptual object list | 15*n |
Perceptual objects:
Message name | Number of bytes occupied |
---|---|
Sensed object id | 1 |
Speed of perceived object | 4 |
Courting angle of perceived object | 2 |
Perceived object longitude | 4 |
Perceived object latitude | 4 |
Then I will build several objects like this in Java to implement the protocol:
structure:
Entity upper layer interface specification: Protocol
public abstract class Protocol {<!-- --> byte[] bytes = new byte[0];//Abstract bytes array, used to store the final bytes of the successor void toBytes() {<!-- -->//Abstract method, constraint subclasses must implement it } }
Message header:
@Data public class ProtocolHead<T extends Protocol> extends Protocol {<!-- --> private byte msgHead; private byte msgType; private byte msgVersion; private long timeStamp; private T msgBody; @Override public void toBytes() {<!-- --> msgBody.toBytes();//Array msgBody bytes ByteBuffer buffer = ByteBuffer.allocate(1 + 1 + 1 + 8 + msgBody.bytes.length); buffer.put(msgHead); buffer.put(msgType); buffer.put(msgVersion); buffer.putLong(timeStamp); buffer.put(msgBody.bytes); bytes = buffer.array(); } }
Message body:
@Data public class ProtocolBody extends Protocol {<!-- --> private byte perNum; private PerceptionData[] perceptionDataArr; @Override public void toBytes() {<!-- --> int size = 1; for (byte i = 0; i < perNum; i + + ) {<!-- --> perceptionDataArr[i].toBytes();//Byteize each perception object size + = perceptionDataArr[i].bytes.length; } ByteBuffer buffer = ByteBuffer.allocate(size); for (byte i = 0; i < perNum; i + + ) {<!-- --> buffer.put(perceptionDataArr[i].bytes); } bytes=buffer.array(); } }
Message content:
@Data public class PerceptionData extends Protocol {<!-- --> private byte id; private int speed; private short heading; private int lon; private int lat; @Override public void toBytes() {<!-- --> ByteBuffer buffer = ByteBuffer.allocate(1 + 4 + 2 + 4 + 4); buffer.put(id); buffer.putInt(speed); buffer.putShort(heading); buffer.putInt(lon); buffer.putInt(lat); bytes= buffer.array(); } }
Input data (data incoming from the simulated device)
@Data public class InputPerData {<!-- --> private long timeStamp; private List<Per> perList; @Data public static class Per {<!-- --> private byte id; private int speed; private short heading; private int lon; private int lat; } }
Parsing class convert conversion:
public class EncodeParser {<!-- --> public byte[] convertData(InputPerData inputPerData) {<!-- --> PerceptionData[] perArr = new PerceptionData[inputPerData.getPerList().size()]; for (int i = 0; i < inputPerData.getPerList().size(); i + + ) {<!-- --> InputPerData.Per inputPer = inputPerData.getPerList().get(i); perArr[i] = new PerceptionData(); perArr[i].setId(inputPer.getId()); perArr[i].setSpeed(inputPer.getSpeed()); perArr[i].setHeading(inputPer.getHeading()); perArr[i].setLon(inputPer.getLon()); perArr[i].setLat(inputPer.getLat()); } ProtocolBody body = new ProtocolBody(); body.setPerNum((byte) inputPerData.getPerList().size()); body.setPerceptionDataArr(perArr); ProtocolHead<ProtocolBody> head = new ProtocolHead<>(); head.setMsgHead((byte) 0x01); head.setMsgType((byte) 0x04); head.setMsgVersion((byte) 0x01); head.setTimeStamp(inputPerData.getTimeStamp()); head.setMsgBody(body); head.toBytes();//Call encoding method return head.bytes; } public static void main(String[] args) {<!-- --> InputPerData.Per per = new InputPerData.Per(); per.setId((byte) 1); per.setSpeed(11); per.setHeading((short) 180); per.setLon(111342345); per.setLat(260099888); InputPerData.Per per1 = new InputPerData.Per(); per1.setId((byte) 2); per1.setSpeed(10); per1.setHeading((short) 120); per1.setLon(114909989); per1.setLat(269894903); EncodeParser parser = new EncodeParser(); InputPerData input = new InputPerData(); input.setTimeStamp(System.currentTimeMillis()); input.setPerList(Lists.newArrayList(per, per1)); byte[] bytes = parser.convertData(input); //Final byte is used for network communication, commonly used in netty's tcp/udp communication System.out.println("bytes = " + Arrays.toString(bytes)); } }
I feel that this can reduce intrusive calculations inside the code, and it is more convenient to write custom protocols;
If there are any shortcomings in the article, please correct me and I will edit it.
Of course, if the bosses have any better methods, we can communicate with them.