mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 23:23:55 +08:00
Merge pull request #3301 from chentyke/fix/issue-3299-auto-update-state
fix: 修复设备自动升级开关状态不生效
This commit is contained in:
+4
-2
@@ -125,7 +125,9 @@ public class DeviceController {
|
||||
return new Result<Void>().error("设备不存在");
|
||||
}
|
||||
BeanUtils.copyProperties(deviceUpdateDTO, entity);
|
||||
deviceService.updateById(entity);
|
||||
if (!deviceService.updateById(entity)) {
|
||||
return new Result<Void>().error(ErrorCode.UPDATE_DATA_FAILED);
|
||||
}
|
||||
return new Result<Void>();
|
||||
}
|
||||
|
||||
@@ -211,4 +213,4 @@ public class DeviceController {
|
||||
deviceAddressBookService.saveOrUpdate(dto.getMacAddress(), dto.getTargetMac(), null, dto.getHasPermission());
|
||||
return new Result<Void>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -202,8 +202,8 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
firmware.setUrl(Constant.INVALID_FIRMWARE_URL);
|
||||
response.setFirmware(firmware);
|
||||
} else {
|
||||
// 只有在设备已绑定且autoUpdate不为0的情况下才返回固件升级信息
|
||||
if (deviceById.getAutoUpdate() != 0) {
|
||||
// 只有在设备已绑定且明确开启自动升级时才返回固件升级信息
|
||||
if (Integer.valueOf(1).equals(deviceById.getAutoUpdate())) {
|
||||
String type = deviceReport.getBoard() == null ? null : deviceReport.getBoard().getType();
|
||||
DeviceReportRespDTO.Firmware firmware = buildFirmwareInfo(type,
|
||||
deviceReport.getApplication() == null ? null : deviceReport.getApplication().getVersion());
|
||||
@@ -299,6 +299,7 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
UserShowDeviceListVO vo = ConvertUtils.sourceToTarget(device, UserShowDeviceListVO.class);
|
||||
vo.setDeviceType(device.getBoard());
|
||||
vo.setBoard(device.getBoard());
|
||||
vo.setAutoUpdate(device.getAutoUpdate());
|
||||
vo.setCreateDateTimestamp(toTimestamp(device.getCreateDate()));
|
||||
vo.setLastConnectedAtTimestamp(toTimestamp(device.getLastConnectedAt()));
|
||||
return vo;
|
||||
|
||||
@@ -32,8 +32,8 @@ public class UserShowDeviceListVO {
|
||||
@Schema(description = "设备别名")
|
||||
private String alias;
|
||||
|
||||
@Schema(description = "开启OTA")
|
||||
private Integer otaUpgrade;
|
||||
@Schema(description = "自动更新开关(0关闭/1开启)")
|
||||
private Integer autoUpdate;
|
||||
|
||||
@Schema(description = "最近对话时间")
|
||||
private String recentChatTime;
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package xiaozhi.modules.device.controller;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import xiaozhi.common.exception.ErrorCode;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.common.user.UserDetail;
|
||||
import xiaozhi.common.utils.MessageUtils;
|
||||
import xiaozhi.common.utils.Result;
|
||||
import xiaozhi.modules.device.dto.DeviceUpdateDTO;
|
||||
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||
import xiaozhi.modules.device.service.DeviceAddressBookService;
|
||||
import xiaozhi.modules.device.service.DeviceService;
|
||||
import xiaozhi.modules.security.user.SecurityUser;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
|
||||
@DisplayName("设备更新接口回归测试")
|
||||
class DeviceControllerTest {
|
||||
|
||||
private static final String DEVICE_ID = "device-id";
|
||||
private static final long USER_ID = 1L;
|
||||
|
||||
@Test
|
||||
@DisplayName("数据库未更新时不误报自动升级状态修改成功")
|
||||
void updateFailureIsReturnedToCaller() {
|
||||
DeviceService deviceService = mock(DeviceService.class);
|
||||
DeviceEntity entity = ownedDevice();
|
||||
when(deviceService.selectById(DEVICE_ID)).thenReturn(entity);
|
||||
when(deviceService.updateById(entity)).thenReturn(false);
|
||||
DeviceController controller = controller(deviceService);
|
||||
|
||||
DeviceUpdateDTO update = new DeviceUpdateDTO();
|
||||
update.setAutoUpdate(0);
|
||||
|
||||
try (MockedStatic<SecurityUser> securityUser = mockStatic(SecurityUser.class);
|
||||
MockedStatic<MessageUtils> messageUtils = mockStatic(MessageUtils.class)) {
|
||||
securityUser.when(SecurityUser::getUser).thenReturn(currentUser());
|
||||
messageUtils.when(() -> MessageUtils.getMessage(ErrorCode.UPDATE_DATA_FAILED))
|
||||
.thenReturn("Failed to update data");
|
||||
|
||||
Result<Void> result = controller.updateDeviceInfo(DEVICE_ID, update);
|
||||
|
||||
assertEquals(ErrorCode.UPDATE_DATA_FAILED, result.getCode());
|
||||
assertEquals(0, entity.getAutoUpdate());
|
||||
verify(deviceService).updateById(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private DeviceController controller(DeviceService deviceService) {
|
||||
return new DeviceController(
|
||||
deviceService,
|
||||
mock(DeviceAddressBookService.class),
|
||||
mock(RedisUtils.class),
|
||||
mock(SysParamsService.class));
|
||||
}
|
||||
|
||||
private DeviceEntity ownedDevice() {
|
||||
DeviceEntity entity = new DeviceEntity();
|
||||
entity.setId(DEVICE_ID);
|
||||
entity.setUserId(USER_ID);
|
||||
entity.setAutoUpdate(1);
|
||||
return entity;
|
||||
}
|
||||
|
||||
private UserDetail currentUser() {
|
||||
UserDetail user = new UserDetail();
|
||||
user.setId(USER_ID);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package xiaozhi.modules.device.service.impl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
import xiaozhi.common.constant.Constant;
|
||||
import xiaozhi.modules.device.dto.DeviceReportReqDTO;
|
||||
import xiaozhi.modules.device.dto.DeviceReportRespDTO;
|
||||
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||
import xiaozhi.modules.device.service.OtaService;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
|
||||
@DisplayName("设备自动升级回归测试")
|
||||
class DeviceAutoUpdateTest {
|
||||
|
||||
private static final String MAC_ADDRESS = "00:11:22:33:44:55";
|
||||
private static final String BOARD_TYPE = "test-board";
|
||||
private static final String CURRENT_VERSION = "1.0.0";
|
||||
|
||||
@Test
|
||||
@DisplayName("#3299 自动升级关闭时 OTA 响应不包含固件")
|
||||
void disabledAutoUpdateOmitsFirmware() {
|
||||
OtaService otaService = mock(OtaService.class);
|
||||
DeviceServiceImpl service = proxiedService(deviceWithAutoUpdate(0), otaService);
|
||||
|
||||
DeviceReportRespDTO response = service.checkDeviceActive(
|
||||
MAC_ADDRESS, MAC_ADDRESS, deviceReport());
|
||||
|
||||
assertNull(response.getFirmware());
|
||||
verifyNoInteractions(otaService);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("自动升级开启时继续执行固件查询")
|
||||
void enabledAutoUpdateChecksFirmware() {
|
||||
OtaService otaService = mock(OtaService.class);
|
||||
when(otaService.getLatestOta(BOARD_TYPE)).thenReturn(null);
|
||||
DeviceServiceImpl service = proxiedService(deviceWithAutoUpdate(1), otaService);
|
||||
|
||||
DeviceReportRespDTO response = service.checkDeviceActive(
|
||||
MAC_ADDRESS, MAC_ADDRESS, deviceReport());
|
||||
|
||||
assertNotNull(response.getFirmware());
|
||||
assertEquals(CURRENT_VERSION, response.getFirmware().getVersion());
|
||||
assertEquals(Constant.INVALID_FIRMWARE_URL, response.getFirmware().getUrl());
|
||||
verify(otaService).getLatestOta(BOARD_TYPE);
|
||||
}
|
||||
|
||||
private DeviceServiceImpl proxiedService(DeviceEntity device, OtaService otaService) {
|
||||
SysParamsService sysParamsService = mock(SysParamsService.class);
|
||||
when(sysParamsService.getValue(Constant.SERVER_WEBSOCKET, true))
|
||||
.thenReturn("ws://127.0.0.1:8000/xiaozhi/v1/");
|
||||
when(sysParamsService.getValue(Constant.SERVER_AUTH_ENABLED, true)).thenReturn("false");
|
||||
when(sysParamsService.getValue(Constant.SERVER_MQTT_GATEWAY, true)).thenReturn(null);
|
||||
|
||||
DeviceServiceImpl target = new DeviceServiceImpl(
|
||||
null, null, sysParamsService, null, otaService, null) {
|
||||
@Override
|
||||
public DeviceEntity getDeviceByMacAddress(String macAddress) {
|
||||
return device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDeviceConnectionInfo(String agentId, String deviceId, String appVersion) {
|
||||
// No-op: connection timestamps are outside this OTA decision test.
|
||||
}
|
||||
};
|
||||
|
||||
ProxyFactory proxyFactory = new ProxyFactory(target);
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
proxyFactory.setExposeProxy(true);
|
||||
return (DeviceServiceImpl) proxyFactory.getProxy();
|
||||
}
|
||||
|
||||
private DeviceEntity deviceWithAutoUpdate(int autoUpdate) {
|
||||
DeviceEntity device = new DeviceEntity();
|
||||
device.setId(MAC_ADDRESS);
|
||||
device.setMacAddress(MAC_ADDRESS);
|
||||
device.setBoard(BOARD_TYPE);
|
||||
device.setAutoUpdate(autoUpdate);
|
||||
return device;
|
||||
}
|
||||
|
||||
private DeviceReportReqDTO deviceReport() {
|
||||
DeviceReportReqDTO.Application application = new DeviceReportReqDTO.Application();
|
||||
application.setVersion(CURRENT_VERSION);
|
||||
DeviceReportReqDTO.BoardInfo board = new DeviceReportReqDTO.BoardInfo();
|
||||
board.setType(BOARD_TYPE);
|
||||
|
||||
DeviceReportReqDTO report = new DeviceReportReqDTO();
|
||||
report.setApplication(application);
|
||||
report.setBoard(board);
|
||||
return report;
|
||||
}
|
||||
}
|
||||
+19
@@ -76,6 +76,25 @@ class DeviceTimeSerializationTest {
|
||||
() -> assertTrue(payload.path("createDate").isNull()));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "自动升级状态 {0}")
|
||||
@ValueSource(ints = { 0, 1 })
|
||||
@DisplayName("#3299 设备列表按 autoUpdate 契约返回真实开关状态")
|
||||
void serializedDeviceContainsAutoUpdateState(int autoUpdate) {
|
||||
DeviceEntity entity = new DeviceEntity();
|
||||
entity.setAutoUpdate(autoUpdate);
|
||||
DeviceServiceImpl deviceService = serviceReturning(entity);
|
||||
|
||||
UserShowDeviceListVO device = deviceService.getUserDeviceList(1L, "agent-id").getFirst();
|
||||
ObjectMapper objectMapper = new WebMvcConfig().jackson2HttpMessageConverter().getObjectMapper();
|
||||
JsonNode payload = objectMapper.valueToTree(device);
|
||||
|
||||
assertAll(
|
||||
() -> assertEquals(autoUpdate, device.getAutoUpdate()),
|
||||
() -> assertEquals(autoUpdate, payload.path("autoUpdate").asInt()),
|
||||
() -> assertTrue(payload.path("otaUpgrade").isMissingNode(),
|
||||
"设备列表不应继续暴露未映射的旧字段 otaUpgrade"));
|
||||
}
|
||||
|
||||
private DeviceServiceImpl serviceReturning(DeviceEntity entity) {
|
||||
return new DeviceServiceImpl(null, null, null, null, null, null) {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user