package com.ruoyi.iot.service; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.constant.IotConstants; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.utils.oneNet.Token; import com.ruoyi.iot.domain.CurrentDeviceData; import com.ruoyi.iot.domain.HistoryDeviceData; import com.ruoyi.iot.domain.IotDeviceDetail; import com.ruoyi.iot.domain.IotDeviceInfo; import com.ruoyi.iot.domain.response.CommandResponse; import com.ruoyi.iot.domain.response.CurrentDataPointResponse; import com.ruoyi.iot.domain.response.DetailResponse; import com.ruoyi.iot.domain.response.HistoryDataPointResponse; import com.ruoyi.iot.util.CommandBuilder; import com.ruoyi.ss.device.domain.SmDevice; import com.ruoyi.ss.device.domain.enums.DeviceOnlineStatus; import com.ruoyi.ss.device.domain.enums.DeviceOutageWay; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * @author wjh * 2024/3/20 */ @Service @Slf4j public class IotServiceImpl implements IotService { @Value("${sm.iotHost}") private String iotHost; @Value(value = "${sm.productId}") private String productId; @Value(value = "${sm.version}") private String version; @Value(value = "${sm.resourceName}") private String resourceName; @Value(value = "${sm.accessKey}") private String accessKey; @Value(value = "${sm.timeout}") private String timeout; @Value(value = "${sm.daysToExpire}") private Long daysToExpire; @Value(value = "${debug}") private Boolean debug; // 查询OneNet设备在线状态 @Override public DeviceOnlineStatus getOnlineStatus(String deviceName) { if (StringUtils.isBlank(deviceName)) { return DeviceOnlineStatus.OFFLINE; } // CommandResponse response = sendCommand(deviceName, "111"); // return HttpStatus.IOT_SUCCESS.equals(response.getCode()) ? DeviceOnlineStatus.ONLINE : DeviceOnlineStatus.OFFLINE; IotDeviceDetail detail = this.getDeviceDetail(deviceName); if (detail == null) { return DeviceOnlineStatus.OFFLINE; } return IotDeviceDetail.Status.toDeviceOnlineStatus(detail.getStatus()); } // 通电 @Override public boolean open(String deviceName) { CommandResponse response = sendCommand(deviceName, IotConstants.COMMAND_OPEN); ServiceUtil.assertion(!HttpStatus.IOT_SUCCESS.equals(response.getCode()), "通电发生异常:" + response.getMsg()); return HttpStatus.IOT_SUCCESS.equals(response.getCode()); } // 断电 @Override public boolean close(String deviceName) { CommandResponse response = sendCommand(deviceName, IotConstants.COMMAND_CLOSE); ServiceUtil.assertion(!HttpStatus.IOT_SUCCESS.equals(response.getCode()), "断电发生异常:" + response.getMsg()); return HttpStatus.IOT_SUCCESS.equals(response.getCode()); } // 获取历史设备数据点信息 @Override public HistoryDeviceData getHistoryDataPoint(String deviceName) { String param = "device_name=" + deviceName + "&product_id=" + productId; String sendUrl = iotHost + IotConstants.ADDS_HISTORY_DATAPOINTS + "?"+param; String token = Token.getToken(); log.info("IOT获取到Authorization:【{}】",token); String result = HttpUtils.sendGetWithToken(sendUrl, null, token); log.info("IOT返回的结果【{}】",result); if (!StringUtils.hasText(result)) { log.error("与OneNet通信异常"); return null; } HistoryDataPointResponse response = JSONObject.parseObject(result, HistoryDataPointResponse.class); if (!HttpStatus.IOT_SUCCESS.equals(response.getCode())) { log.error("获取历史设备数据点信息出错:" + response.getMsg()); return null; } return response.getData(); } // 获取当前设备数据点信息 @Override public List getCurrentDataPoint(List deviceNames) { String param = "device_name=" + String.join(",", deviceNames) + "&product_id=" + productId; String sendUrl = iotHost+ IotConstants.ADDS_CURRENT_DATAPOINTS + "?" + param; String result = HttpUtils.sendGetWithToken(sendUrl, null, Token.getToken()); log.info("IOT返回的结果【{}】", result); if (!StringUtils.hasText(result)) { log.error("与OneNet通信异常"); return Collections.emptyList(); } CurrentDataPointResponse response = JSONObject.parseObject(result, CurrentDataPointResponse.class); if (!HttpStatus.IOT_SUCCESS.equals(response.getCode())) { log.error("获取当前设备数据点信息出错:" + response.getMsg()); return Collections.emptyList(); } return response.getData().getDevices(); } // 获取当前设备数据点信息 @Override public CurrentDeviceData getCurrentDataPoint(String deviceName) { List list = this.getCurrentDataPoint(Collections.singletonList(deviceName)); if (CollectionUtils.isEmpty(list)) { return null; } return list.stream().filter(item -> Objects.equals(item.getTitle(), deviceName)).findFirst().orElse(null); } @Override public IotDeviceDetail getDeviceDetail(String deviceName) { String sendUrl = iotHost + IotConstants.ADDS_DEVICE_DETAIL; String param = "device_name=" + deviceName + "&product_id=" + productId; String token = Token.getToken(); log.info("IOT获取到Authorization:【{}】",token); String result = HttpUtils.sendGetWithToken(sendUrl, param, token); if (!StringUtils.hasText(result)) { log.error("与OneNet通信异常"); return null; } DetailResponse response = JSONObject.parseObject(result, DetailResponse.class); if (!HttpStatus.IOT_SUCCESS.equals(response.getCode())) { log.error("获取当前设备数据点信息出错:{}", response.getMsg()); return null; } return response.getData(); } /** * 设置剩余时长 * * @param deviceName 设备名称 * @param seconds 时长(秒) * @return 是否成功 */ @Override @Transactional public CommandResponse setTime(String deviceName, BigDecimal seconds) { if (seconds == null || BigDecimal.ZERO.compareTo(seconds) > 0) { throw new ServiceException("设置剩余时长参数错误:读数不允许为空或者小于0"); } return sendCommand(deviceName, IotConstants.COMMAND_RECHARGE + seconds + IotConstants.COMMAND_SEPARATOR); } /** * 更新设备信息 * @param device 设备信息 */ @Override @Transactional public boolean updateDevice(SmDevice device) { // DEBUG模式下直接返回true if (debug) { return true; } DeviceOutageWay deviceOutageWay = DeviceOutageWay.parse(device.getOutageWay()); String command = CommandBuilder.builder() // 断电方式,若为空,则立即断电 .setIfNull(IotConstants.COMMAND_OUTAGE_WAY, deviceOutageWay.getValue() , DeviceOutageWay.IMMEDIATE.getValue()) .build(); CommandResponse response = sendCommand(device.getMac(), command); ServiceUtil.assertion(!Objects.equals(HttpStatus.IOT_SUCCESS, response.getCode()), "修改设备设置发生异常:" + response.getMsg()); return true; } @Override public IotDeviceInfo getDeviceInfo(String deviceName) { if (StringUtils.isBlank(deviceName)) { return null; } CurrentDeviceData currentDataPoint = getCurrentDataPoint(deviceName); if (currentDataPoint == null) { return null; } return currentDataPoint.parseDeviceInfo(); } @Override public List getDeviceInfo(List deviceNames) { if (CollectionUtils.isEmpty(deviceNames)) { return Collections.emptyList(); } List dataList = getCurrentDataPoint(deviceNames); if (CollectionUtils.isEmpty(dataList)) { return Collections.emptyList(); } return dataList.stream().map(CurrentDeviceData::parseDeviceInfo).collect(Collectors.toList()); } // 发送MQTT命令 @Override public CommandResponse sendCommand(String deviceName, String command) { String sendUrl = iotHost + IotConstants.ADDS_COMMAND; String param = "device_name=" + deviceName + "&product_id=" + productId +"&timeout=" + timeout; sendUrl = sendUrl + "?" + param; String token = Token.getToken(); String result = HttpUtils.sendPostWithToken(sendUrl, command, token); ServiceUtil.assertion(!StringUtils.hasText(result), "与OneNet通信异常"); return JSON.parseObject(result, CommandResponse.class); } }