CoapEncoder implements StatelessProtocolEncoder<CoapMessage, ByteBuffer> { @Override public ByteBuffer encode(CoapMessage message, Void context) { LOG.debug("encoding {}", message); int size = HEADER_SIZE + message.getToken().length; int delta = 0; for (CoapOption opt : message.getOptions()) { int code = opt.getType().getCode(); delta = code - delta; if (delta < 13) { size += 1; } else if (delta < 256 + 13) { size += 2; } else if (delta < 65536 + 269) { size += 3; } int optLength = opt.getData().length; if (optLength < 13) { size += 0; } else if (optLength < 256 + 13) { size += 1; } else if (optLength < 65536 + 269) { size += 2; } size += optLength; } if (message.getPayload() != null && message.getPayload().length > 0) { size += 1; size += message.getPayload().length; } ByteBuffer buffer = ByteBuffer.allocate(size); buffer.order(ByteOrder.BIG_ENDIAN); buffer.put((byte) (((message.getVersion() & 0x03) << 6) | (message.getType().getCode() & 0x03) << 4 | (message .getToken().length & 0x0F))); buffer.put((byte) message.getCode()); buffer.putShort((short) message.getId()); buffer.put(message.getToken()); int lastOptCode = 0; for (CoapOption opt : message.getOptions()) { int optionDelta = opt.getType().getCode() - lastOptCode; int deltaQuartet = getQuartet(optionDelta); int optionLength = opt.getData().length; int optionQuartet = getQuartet(optionLength); buffer.put((byte) ((deltaQuartet << 4) | optionQuartet)); if (deltaQuartet == 13) { buffer.put((byte) (optionDelta - 13)); } else if (deltaQuartet == 14) { buffer.putShort((short) (optionDelta - 269)); } if (optionQuartet == 13) { buffer.put((byte) (optionLength - 13)); } else if (optionQuartet == 14) { buffer.putShort((short) (optionLength - 269)); } buffer.put(opt.getData()); lastOptCode = opt.getType().getCode(); } if (message.getPayload() != null && message.getPayload().length > 0) { buffer.put((byte) 0xFF); buffer.put(message.getPayload()); } buffer.flip(); return buffer; }  @Override Void createEncoderState(); @Override ByteBuffer encode(CoapMessage message, Void context);  }
@Test public void no_content_no_option() { CoapMessage message = NO_CONTENT_NO_OPTION; ByteBuffer encoded = encoder.encode(message, null); Assert.assertEquals(NO_CONTENT_NO_OPTION_HEX, ByteBufferDumper.toHex(encoded)); }
@Test public void some_content_no_option() { CoapMessage message = SOME_CONTENT_NO_OPTION; ByteBuffer encoded = encoder.encode(message, null); Assert.assertEquals(SOME_CONTENT_NO_OPTION_HEX, ByteBufferDumper.toHex(encoded)); }
@Test public void payload_and_one_option() { CoapMessage message = PAYLOAD_AND_ONE_OPTION; ByteBuffer encoded = encoder.encode(message, null); Assert.assertEquals(PAYLOAD_AND_ONE_OPTION_HEX, ByteBufferDumper.toHex(encoded)); }
@Test public void payload_and_multiple_option() { CoapMessage message = PAYLOAD_AND_MULTIPLE_OPTION; ByteBuffer encoded = encoder.encode(message, null); Assert.assertEquals(PAYLOAD_AND_MULTIPLE_OPTION_HEX, ByteBufferDumper.toHex(encoded)); }
@Test public void observe() { CoapMessage message = OBSERVE; ByteBuffer encoded = encoder.encode(message, null); Assert.assertEquals(OBSERVE_HEX, ByteBufferDumper.toHex(encoded)); }