class EncodeContext {

        private final DeviceMessage source;
        private ByteBuf payload;
        private final Map<String, Object> headers = new HashMap<>();

        public EncodeContext(DeviceMessage source) {
            this.source = source;
        }

        public DeviceMessage message() {
            return source;
        }

        public EncodeContext topic(String topic) {
            headers.put("topic", topic);
            return this;
        }

        public ByteBuf payload() {
            return payload == null ? payload = Unpooled.buffer() : payload;
        }

        public ByteBuf newBuffer() {
            return Unpooled.buffer();
        }

        @SneakyThrows
        public EncodeContext setPayload(String strOrHex, String charset) {
            if (strOrHex.startsWith("0x")) {
                payload().writeBytes(Hex.decodeHex(strOrHex.substring(2)));
            } else {
                payload().writeBytes(strOrHex.getBytes(charset));
            }
            return this;
        }

        @SneakyThrows
        public EncodeContext setPayload(String strOrHex) {
            setPayload(strOrHex, "utf-8");
            return this;
        }

        public EncodeContext setPayload(Object data) {

            if (data instanceof String) {
                setPayload(((String) data));
            }

            if (data instanceof byte[]) {
                payload().writeBytes(((byte[]) data));
            }

            if (data instanceof ByteBuf) {
                this.payload = ((ByteBuf) data);
            }
            //todo 更多类型?

            return this;
        }

        public EncodeContext whenFunction(String functionId, Function<Object, Object> supplier) {
            if (source instanceof ThingFunctionInvokeMessage) {
                ThingFunctionInvokeMessage<?> msg = ((ThingFunctionInvokeMessage<?>) source);
                if ("*".equals(msg.getFunctionId()) || Objects.equals(functionId, msg.getFunctionId())) {
                    setPayload(supplier.apply(msg.inputsToMap()));
                }
            }
            return this;
        }

        public EncodeContext whenWriteProperty(String property, Function<Object, Object> supplier) {<FILL_FUNCTION_BODY>}

        public EncodeContext whenReadProperties(Function<List<String>, Object> supplier) {
            if (source instanceof ReadThingPropertyMessage) {
                setPayload(supplier.apply(((ReadThingPropertyMessage<?>) source).getProperties()));
            }
            return this;
        }

        public EncodeContext whenReadProperty(String property, Supplier<Object> supplier) {
            if (source instanceof ReadThingPropertyMessage) {
                if ("*".equals(property) || ((ReadThingPropertyMessage<?>) source).getProperties().contains(property)) {
                    setPayload(supplier.get());
                }
            }
            return this;
        }
    }

            if (source instanceof WriteThingPropertyMessage) {
                if ("*".equals(property)) {
                    setPayload(supplier.apply(((WriteThingPropertyMessage<?>) source).getProperties()));
                    return this;
                }
                Object value = ((WriteThingPropertyMessage<?>) source).getProperties().get(property);
                if (value != null) {
                    setPayload(supplier.apply(value));
                }
            }
            return this;
        
<no_super_class>