package com.ruoyi.web.app; import java.math.BigDecimal; import java.util.function.Supplier; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.bst.device.domain.DeviceVO; import com.ruoyi.bst.device.domain.dto.DeviceBltUploadDTO; import com.ruoyi.bst.device.service.DeviceIotService; import com.ruoyi.bst.device.service.DeviceService; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.redis.RedisLock; import com.ruoyi.common.core.redis.enums.RedisLockKey; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.LogBizType; import com.ruoyi.common.utils.MathUtils; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.map.GeoUtils; import com.ruoyi.iot.constants.IotConstants; import io.swagger.annotations.ApiOperation; @RestController @RequestMapping("/app/device/iot") public class AppDeviceIotController extends BaseController { @Autowired private DeviceIotService deviceIotService; @Autowired private DeviceService deviceService; @Autowired private RedisLock redisLock; /** * 执行带设备锁的操作 * @param device 设备信息 * @param operation 具体操作 * @return 操作结果 */ private AjaxResult executeWithLock(Long deviceId, Supplier operation) { ServiceUtil.assertion(deviceId == null, "设备ID不能为空"); // 获取设备锁 boolean lock = redisLock.lock(RedisLockKey.DEVICE_IOT_OPERATION, deviceId); if (!lock) { return AjaxResult.error("设备操作过于频繁,请稍后再试"); } try { return operation.get(); } finally { redisLock.unlock(RedisLockKey.DEVICE_IOT_OPERATION, deviceId); } } private DeviceVO getDevice(Long id, String sn) { if (id != null) { return deviceService.selectDeviceById(id); } else { return deviceService.selectDeviceBySn(sn); } } @ApiOperation("用户响铃寻车") @PutMapping("/ring") @Log(title = "用户响铃寻车", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE) public AjaxResult ring(@RequestParam(required = false) Long id, @RequestParam(required = false) String sn, @RequestParam(required = false) BigDecimal lon, @RequestParam(required = false) BigDecimal lat) { DeviceVO device = getDevice(id, sn); ServiceUtil.assertion(device == null, "当前车辆不存在,无法响铃寻车"); if (device.getAreaRequiredRingRadius() != null && device.getAreaRequiredRingRadius()) { ServiceUtil.assertion(lon == null || lat == null, "请开启定位后重试"); BigDecimal distance = GeoUtils.calculateDistance(device.getLatitude(), device.getLongitude(), lat, lon); ServiceUtil.assertion(MathUtils.biggerThan(distance, device.getAreaRingRadius()), "您当前距离车辆%s米,无法响铃寻车。请距离车辆%s米以内再试", distance, device.getAreaRingRadius()); } return executeWithLock(device.getId(), () -> { return toAjax(deviceIotService.play(device, IotConstants.PLAY_WARNING, "用户响铃寻车", true)); }); } @ApiOperation("蓝牙上传设备信息") @PutMapping("/bltUpload") @Log(title = "蓝牙上传设备信息", businessType = BusinessType.OTHER, bizType = LogBizType.DEVICE) public AjaxResult bltUpload(@RequestBody @Validated DeviceBltUploadDTO dto) { return toAjax(deviceIotService.bltUpload(dto)); } }