【设备端物模型历史数据上报】代码实现与技术手册中协议不一致,导致broker解析异常

IOT 未结 2 187
hanbd
hanbd 2025-02-12 11:29

一、该问题的重现步骤是什么?

  1. 按 技术手册 -》序言 -》 协议介绍 -》6.6 设备端物模型历史数据上报 中描述的请求数据格式组织数据。

  2. 向对应Topic发送mqtt数据

  3. broker报解析异常


二、你期待的结果是什么?实际看到的又是什么?

期待结果:能够按照技术手册 -》序言 -》 协议介绍 -》6.6 设备端物模型历史数据上报 章节描述的消息体格式批量进行历史数据上报

实际看到的:

  1. 技术手册协议描述中,properties支持数组格式,对于单个设备来说,可以一次上传多条数据

  2. broker中代码实现中,properties为Map格式,与协议不一致,对应类


org.springblade.mqtt.broker.data.function.event.EventPropertyHistoryPostFunction
org.springblade.mqtt.broker.data.protocol.event.PropertyHistoryPostReq

image.png

image.png

三、你正在使用的是什么产品,什么版本?在什么操作系统上?

Blade-Links

v1.3.0

Windows 11


四、请提供详细的错误堆栈信息,这很重要。

示例数据:

{
	"id": "5d75530cc1dad31cec48e954ad93a92a",
	"version": "1.0",
	"sys": {
		"ack": 0
	},
	"method": "thing.event.property.history.post",
	"params": [{
		"identity": {
			"productKey": "ZT_slj",
			"deviceName": "jd_slj_1"
		},
		"properties": [{
			"cf": {
				"value": 1.094759,
				"time": 1739327857344
			}
		}, {
			"cf": {
				"value": 7.7139072,
				"time": 1739327862344
			}
		}, {
			"cf": {
				"value": 3.0228767,
				"time": 1739327867344
			}
		}]
	}]
}

broker异常信息:

2025-02-12 11:27:32.534 ERROR 22292 --- [  biz-worker-31] n.d.i.m.c.s.s.DefaultMqttServerProcessor : com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.LinkedHashMap` from Array value (token `JsonToken.START_ARRAY`)
 at [Source: (byte[])"{"id":"ffa6ad5ece6498cdddf5b4db1a7829ff","version":"1.0","sys":{"ack":0},"method":"thing.event.property.history.post","params":[{"identity":{"productKey":"ZT_slj","deviceName":"jd_slj_1"},"properties":[{"cf":{"value":8.746042,"time":1739330847926}},{"cf":{"value":-5.9267864,"time":1739330852926}},{"cf":{"value":5.870201,"time":1739330857926}}]}]}"; line: 1, column: 202] (through reference chain: org.springblade.mqtt.broker.data.protocol.core.DataReq["params"]->java.util.ArrayList[0]->org.springblade.mqtt.broker.data.protocol.event.PropertyHistoryPostReq["properties"])

java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.LinkedHashMap` from Array value (token `JsonToken.START_ARRAY`)
 at [Source: (byte[])"{"id":"ffa6ad5ece6498cdddf5b4db1a7829ff","version":"1.0","sys":{"ack":0},"method":"thing.event.property.history.post","params":[{"identity":{"productKey":"ZT_slj","deviceName":"jd_slj_1"},"properties":[{"cf":{"value":8.746042,"time":1739330847926}},{"cf":{"value":-5.9267864,"time":1739330852926}},{"cf":{"value":5.870201,"time":1739330857926}}]}]}"; line: 1, column: 202] (through reference chain: org.springblade.mqtt.broker.data.protocol.core.DataReq["params"]->java.util.ArrayList[0]->org.springblade.mqtt.broker.data.protocol.event.PropertyHistoryPostReq["properties"])
	at org.springblade.core.tool.utils.Exceptions.unchecked(Exceptions.java:46)
	at org.springblade.core.tool.jackson.JsonUtil.readValue(JsonUtil.java:422)
	at org.springblade.mqtt.broker.data.listener.BladeMqttFunctionMessageListener.execDeviceFunction(BladeMqttFunctionMessageListener.java:103)
	at org.springblade.mqtt.broker.data.listener.BladeMqttFunctionMessageListener.execMqttFunction(BladeMqttFunctionMessageListener.java:81)
	at org.springblade.mqtt.broker.data.listener.BladeMqttFunctionMessageListener.lambda$onMessage$0(BladeMqttFunctionMessageListener.java:69)
	at org.springblade.core.tenant.TenantUtil.use(TenantUtil.java:93)
	at org.springblade.mqtt.broker.data.listener.BladeMqttFunctionMessageListener.onMessage(BladeMqttFunctionMessageListener.java:68)
	at net.dreamlu.iot.mqtt.core.server.support.DefaultMqttServerProcessor.lambda$invokeListenerForPublish$4(DefaultMqttServerProcessor.java:514)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:842)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.LinkedHashMap` from Array value (token `JsonToken.START_ARRAY`)
 at [Source: (byte[])"{"id":"ffa6ad5ece6498cdddf5b4db1a7829ff","version":"1.0","sys":{"ack":0},"method":"thing.event.property.history.post","params":[{"identity":{"productKey":"ZT_slj","deviceName":"jd_slj_1"},"properties":[{"cf":{"value":8.746042,"time":1739330847926}},{"cf":{"value":-5.9267864,"time":1739330852926}},{"cf":{"value":5.870201,"time":1739330857926}}]}]}"; line: 1, column: 202] (through reference chain: org.springblade.mqtt.broker.data.protocol.core.DataReq["params"]->java.util.ArrayList[0]->org.springblade.mqtt.broker.data.protocol.event.PropertyHistoryPostReq["properties"])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1752)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1526)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromArray(StdDeserializer.java:222)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:457)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3866)
	at org.springblade.core.tool.jackson.JsonUtil.readValue(JsonUtil.java:420)
	... 12 common frames omitted


五、若有更多详细信息,请在下面提供。

2条回答
  •  hanbd
    hanbd (楼主)
    2025-02-12 13:45

    我简单做了代码修改,临时能达到协议效果,供参考。共有两处修改:

    1. 修改类org.springblade.mqtt.broker.data.protocol.event.PropertyHistoryPostReq

    2. 修改方法org.springblade.mqtt.broker.data.function.event.EventPropertyHistoryPostFunction#saveHistoryData

    package org.springblade.mqtt.broker.data.protocol.event;
    
    import lombok.Data;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * 设备批量上报属性、事件
     *
     * @author L.cm
     */
    @Data
    public class PropertyHistoryPostReq {
        /**
         * 设备信息
         */
        private Map identity;
        /**
         * 属性信息
         */
        private List> properties;
        /**
         * 事件
         */
        private List> events;
    }
    /**
    * 保存数据
    *
    * @param params 历史列表
    */
    private void saveHistoryData(List params) {
       for (PropertyHistoryPostReq param : params) {
          Map identity = param.getIdentity();
          // 设备属性
          List> propertiesList = param.getProperties();
          if (CollectionUtil.isNotEmpty(propertiesList)) {
             propertiesList
                .stream()
                .filter(CollectionUtil::isNotEmpty)
                .forEach(properties -> deviceDataService.saveDeviceProperty(identity, properties));
          }
          // 设备事件
          List> eventsList = param.getEvents();
          if (CollectionUtil.isNotEmpty(eventsList)) {
             eventsList
                .stream()
                .filter(CollectionUtil::isNotEmpty)
                .forEach(events -> deviceDataService.saveDeviceEvent(identity, events));
          }
       }
    }


    ---

    后续版本建议修复该问题

代码语言
提交回复