From 24681c81c09022f584a57006f2534b5f74723414 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 30 六月 2026 09:27:31 +0800
Subject: [PATCH] 初始化项目

---
 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java |  144 +++++++++++++++++++++++++++++++----------------
 1 files changed, 95 insertions(+), 49 deletions(-)

diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java
index 8f87cb8..67be85e 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java
@@ -5,11 +5,15 @@
 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.ThingModelProperty;
 import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper;
 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
+import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
+import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
+import cn.iocoder.yudao.module.iot.service.product.IotProductService;
 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
@@ -17,8 +21,12 @@
 import org.mockito.Mock;
 
 import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import static java.util.Collections.singletonList;
 import static org.junit.jupiter.api.Assertions.*;
@@ -38,6 +46,8 @@
     @Mock
     private IotThingModelService thingModelService;
     @Mock
+    private IotProductService productService;
+    @Mock
     private IotDevicePropertyMapper devicePropertyMapper;
     @Mock
     private DevicePropertyRedisDAO deviceDataRedisDAO;
@@ -54,6 +64,7 @@
         // mock 琛屼负
         when(thingModelService.getThingModelListByProductIdFromCache(device.getProductId()))
                 .thenReturn(singletonList(thingModel));
+        when(thingModelService.convertThingModelPropertyValue(thingModel, 100)).thenReturn(100);
 
         // 璋冪敤
         service.saveDeviceProperty(device, message);
@@ -91,64 +102,99 @@
     }
 
     @Test
-    public void testSaveDeviceProperty_boolFromBooleanTrue() {
-        // 鍑嗗鍙傛暟锛氱墿妯″瀷涓� BOOL锛岃澶囦笂鎶ュ師鐢� boolean true
-        assertBoolValueConvertedToByte(true, (byte) 1);
-    }
-
-    @Test
-    public void testSaveDeviceProperty_boolFromBooleanFalse() {
-        // 鍑嗗鍙傛暟锛氱墿妯″瀷涓� BOOL锛岃澶囦笂鎶ュ師鐢� boolean false
-        assertBoolValueConvertedToByte(false, (byte) 0);
-    }
-
-    @Test
-    public void testSaveDeviceProperty_boolFromStringTrue() {
-        // 鍑嗗鍙傛暟锛氱墿妯″瀷涓� BOOL锛岃澶囦笂鎶ュ瓧绗︿覆 "true"
-        assertBoolValueConvertedToByte("true", (byte) 1);
-    }
-
-    @Test
-    public void testSaveDeviceProperty_boolFromStringFalse() {
-        // 鍑嗗鍙傛暟锛氱墿妯″瀷涓� BOOL锛岃澶囦笂鎶ュ瓧绗︿覆 "false"
-        assertBoolValueConvertedToByte("false", (byte) 0);
-    }
-
-    @Test
-    public void testSaveDeviceProperty_boolFromNumberOne() {
-        // 鍑嗗鍙傛暟锛氱墿妯″瀷涓� BOOL锛岃澶囦笂鎶ユ暟瀛� 1
-        assertBoolValueConvertedToByte(1, (byte) 1);
-    }
-
-    @Test
-    public void testSaveDeviceProperty_boolFromNumberZero() {
-        // 鍑嗗鍙傛暟锛氱墿妯″瀷涓� BOOL锛岃澶囦笂鎶ユ暟瀛� 0
-        assertBoolValueConvertedToByte(0, (byte) 0);
-    }
-
-    /**
-     * 鏍¢獙 BOOL 绫诲瀷灞炴�т笂鎶ュ悗锛屾渶缁堣惤鍒� properties Map 鐨勫�肩被鍨嬩笌鏁板��
-     */
-    private void assertBoolValueConvertedToByte(Object reportedValue, byte expected) {
-        // 鍑嗗鍙傛暟
+    public void testSaveDeviceProperty_convertValueFailed() {
+        // 鍑嗗鍙傛暟锛氱墿妯″瀷瀛樺湪锛屼絾鏄睘鎬у�兼棤娉曟寜鐗╂ā鍨嬭浆鎹�
         IotDeviceDO device = buildDevice();
-        IotThingModelDO thingModel = buildThingModel("PowerSwitch", IotDataSpecsDataTypeEnum.BOOL.getDataType());
+        IotThingModelDO temperature = buildThingModel("Temperature", IotDataSpecsDataTypeEnum.INT.getDataType());
         Map<String, Object> params = new HashMap<>();
-        params.put("PowerSwitch", reportedValue);
+        params.put("Temperature", "abc");
         IotDeviceMessage message = buildMessage(params);
 
-        // mock 琛屼负
+        // mock 鏂规硶
+        when(thingModelService.getThingModelListByProductIdFromCache(device.getProductId()))
+                .thenReturn(singletonList(temperature));
+        when(thingModelService.convertThingModelPropertyValue(temperature, "abc")).thenReturn(null);
+
+        // 璋冪敤锛屽苟鏂█锛氫笉浼氭姏鍑哄紓甯�
+        assertDoesNotThrow(() -> service.saveDeviceProperty(device, message));
+
+        // 鏂█锛氭病鏈夊悎娉曞睘鎬э紝涓嶄細鍐欏叆 TDengine 涓� Redis
+        verify(devicePropertyMapper, never()).insert(any(), any(), anyLong(), anyLong());
+        verify(deviceDataRedisDAO, never()).putAll(anyLong(), any());
+    }
+
+    @Test
+    public void testSaveDeviceProperty_skipNullValue() {
+        // 鍑嗗鍙傛暟锛氬睘鎬у�间负绌猴紝涓嶈兘鍐欏叆 TDengine 涓� Redis
+        IotDeviceDO device = buildDevice();
+        IotThingModelDO thingModel = buildThingModel("Temperature", IotDataSpecsDataTypeEnum.INT.getDataType());
+        Map<String, Object> params = new HashMap<>();
+        params.put("Temperature", null);
+        IotDeviceMessage message = buildMessage(params);
+
+        // mock 鏂规硶
         when(thingModelService.getThingModelListByProductIdFromCache(device.getProductId()))
                 .thenReturn(singletonList(thingModel));
 
-        // 璋冪敤锛氫笉鑳芥姏寮傚父
+        // 璋冪敤锛屽苟鏂█锛氫笉浼氭姏鍑哄紓甯�
         assertDoesNotThrow(() -> service.saveDeviceProperty(device, message));
 
-        // 鏂█锛氬啓鍏ョ殑 value 鏄� byte 绫诲瀷锛屼笖鍊煎尮閰�
+        // 鏂█锛氳烦杩囩┖鍊硷紝涓嶄細杞崲灞炴�у�硷紝涔熶笉浼氬啓鍏� TDengine 涓� Redis
+        verify(thingModelService, never()).convertThingModelPropertyValue(any(), any());
+        verify(devicePropertyMapper, never()).insert(any(), any(), anyLong(), anyLong());
+        verify(deviceDataRedisDAO, never()).putAll(anyLong(), any());
+    }
+
+    @Test
+    public void testSaveDeviceProperty_skipInvalidKeyType() {
+        // 鍑嗗鍙傛暟锛歁ap 涓寘鍚潪瀛楃涓� key锛屼笉鑳藉洜涓哄己杞け璐ュ奖鍝嶅叾瀹冨悎娉曞睘鎬�
+        IotDeviceDO device = buildDevice();
+        IotThingModelDO thingModel = buildThingModel("PowerSwitch", IotDataSpecsDataTypeEnum.BOOL.getDataType());
+        Map<Object, Object> params = new HashMap<>();
+        params.put(123, 1);
+        params.put("PowerSwitch", true);
+        IotDeviceMessage message = buildMessage(params);
+
+        // mock 鏂规硶
+        when(thingModelService.getThingModelListByProductIdFromCache(device.getProductId()))
+                .thenReturn(singletonList(thingModel));
+        when(thingModelService.convertThingModelPropertyValue(thingModel, true)).thenReturn((byte) 1);
+
+        // 璋冪敤锛屽苟鏂█锛氶潪瀛楃涓� key 涓嶅奖鍝嶅叾瀹冨悎娉曞睘鎬�
+        assertDoesNotThrow(() -> service.saveDeviceProperty(device, message));
+
+        // 鏂█锛氬彧鍐欏叆鍚堟硶灞炴��
         Map<String, Object> dbProperties = captureMapperInsertProperties();
-        Object actual = dbProperties.get("PowerSwitch");
-        assertTrue(actual instanceof Byte, "BOOL 灞炴�у簲琚浆涓� Byte 绫诲瀷锛屽疄闄呬负 " + (actual == null ? "null" : actual.getClass()));
-        assertEquals(expected, actual);
+        assertEquals(1, dbProperties.size());
+        assertEquals((byte) 1, dbProperties.get("PowerSwitch"));
+    }
+
+    @Test
+    public void testDefineDevicePropertyData_fieldNameToLowerCase() {
+        // 鍑嗗鍙傛暟锛氬叏澶у啓缂╁啓鍜岄┘宄扮缉鍐欓兘闇�瑕佽浆鎹负 TDengine 瀹為檯鐨勫皬鍐欏瓧娈靛悕
+        Long productId = 2L;
+        IotProductDO product = IotProductDO.builder().id(productId).build();
+        List<IotThingModelDO> thingModels = Arrays.asList(
+                buildThingModel("Ua", IotDataSpecsDataTypeEnum.FLOAT.getDataType()),
+                buildThingModel("PfT", IotDataSpecsDataTypeEnum.FLOAT.getDataType()),
+                buildThingModel("PT", IotDataSpecsDataTypeEnum.FLOAT.getDataType()),
+                buildThingModel("PA", IotDataSpecsDataTypeEnum.FLOAT.getDataType()));
+        thingModels.forEach(thingModel -> thingModel.setType(IotThingModelTypeEnum.PROPERTY.getType()));
+
+        // mock 鏂规硶
+        when(productService.validateProductExists(productId)).thenReturn(product);
+        when(thingModelService.getThingModelListByProductId(productId)).thenReturn(thingModels);
+        when(devicePropertyMapper.getProductPropertySTableFieldList(productId)).thenReturn(Collections.emptyList());
+
+        // 璋冪敤
+        service.defineDevicePropertyData(productId);
+
+        // 鏂█锛氬瓧娈靛悕缁熶竴涓哄皬鍐欎笅鍒掔嚎锛岄伩鍏� PT 鍜屾暟鎹簱涓殑 pt 琚鍒や负涓嶅悓瀛楁
+        ArgumentCaptor<List<TDengineTableField>> captor = ArgumentCaptor.forClass(List.class);
+        verify(devicePropertyMapper).createProductPropertySTable(eq(productId), captor.capture());
+        assertEquals(Arrays.asList("ua", "pf_t", "pt", "pa"), captor.getValue().stream()
+                .map(TDengineTableField::getField)
+                .collect(Collectors.toList()));
     }
 
     // ========== 杈呭姪鏂规硶 ==========
@@ -173,7 +219,7 @@
     /**
      * 鏋勯�犱竴鏉″睘鎬т笂鎶ユ秷鎭�
      */
-    private IotDeviceMessage buildMessage(Map<String, Object> params) {
+    private IotDeviceMessage buildMessage(Map<?, ?> params) {
         IotDeviceMessage message = new IotDeviceMessage();
         message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
         message.setParams(params);

--
Gitblit v1.9.3