完善iotview功能

This commit is contained in:
iteaj
2025-06-20 11:26:50 +08:00
parent abe920e287
commit 8f4ea322df
11 changed files with 238 additions and 52 deletions
@@ -14,6 +14,11 @@ public class ListFetchResult extends ViewFetchResult {
super(item, values);
}
public ListFetchResult addValue(BaseEchartsCount value) {
getValue().add(value);
return this;
}
@Override
public List<BaseEchartsCount> getValue() {
return (List<BaseEchartsCount>) super.getValue();
@@ -0,0 +1,21 @@
package com.iteaj.framework.spi.iot.view;
import lombok.Getter;
/**
* 自定义对象获取
*/
@Getter
public abstract class OriginFetchResult extends ViewFetchResult{
/**
* 是否是原始数据
* 原始数据全段不做处理, 直接渲染
*/
private boolean origin;
public OriginFetchResult(Object value) {
super(null, value);
this.origin = true;
}
}
@@ -26,8 +26,8 @@ public class ViewApiParams {
/**
* 时间范围(格式 yyyy-MM-dd HH:mm)
* 1. 支持具体的时间 如:2024-01-10 15:00 - 2024-01-16 15:00
* 2. 支持now关键字 如:now-6 - now
* 1. 支持具体的时间 如:2024-01-10 15:00,2024-01-16 15:00
* 2. 支持now关键字 如:now-6,now
* @see #timeType
*/
private List<String> timeRange;
@@ -37,6 +37,41 @@ public class ViewApiParams {
*/
private List<Value> values;
/**
* 范围值
*/
private String rangeValue;
/**
* 产品轴类型(time, range)
*/
private String category;
/**
* 范围类型(all、product、device、group...)
*/
private String range;
/**
* 范围值(产品列表, 设备列表, 分组列表, ...)
*/
private List<String> ranges;
public void setRangeValue(String rangeValue) {
this.rangeValue = rangeValue;
if(StrUtil.isNotBlank(rangeValue)) {
final String[] split = rangeValue.split(DataItemOption.SPLIT);
if(split.length == 1) {
this.range = split[0];
} else if(split.length > 1) {
this.range = split[0];
this.ranges = Arrays.asList(split[1].split(","));
} else {
}
}
}
@Getter
@Setter
public static class Value {
@@ -61,20 +96,16 @@ public class ViewApiParams {
*/
private String calcType;
/**
*/
private String range;
/**
* 范围值
*/
private String rangeValue;
private List<String> values;
public Value build() {
if(values != null) {
return this;
}
if(StrUtil.isNotBlank(this.getValue())) {
this.values = Arrays.asList(this.getValue().split(DataItemOption.SPLIT));
this.calcType = this.values.get(this.values.size() - 1);
} else {
throw new ServiceException("项格式错误");
}
@@ -86,6 +117,9 @@ public class ViewApiParams {
if(values == null) {
build();
}
if(index > (this.values.size() - 1)) {
return "";
}
return this.values.get(index);
}
@@ -1,16 +1,16 @@
package com.iteaj.iboot.plugin.iotview.api;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.iteaj.framework.exception.ServiceException;
import com.iteaj.framework.spi.iot.data.BaseEchartsCount;
import com.iteaj.framework.spi.iot.view.*;
import com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto;
import com.iteaj.iboot.plugin.iotview.service.ISVDataService;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
@Component
public class DeviceStatusApiItem implements ViewApiItem {
@@ -19,8 +19,9 @@ public class DeviceStatusApiItem implements ViewApiItem {
private static final String NAME = "设备状态";
private final ISVDataService isvDataService;
private List<DataItemOption> options = Arrays.asList(new DataItemOption("设备状态", KEY)
.asName().builder()
private List<DataItemOption> options = Arrays.asList(new DataItemOption("设备状态", KEY).asName().builder()
.addNameChild("总设备数", "all", true)
.toParent()
.addNameChild("在线", "online")
.addNameChild("统计", "count", true)
.toParent()
@@ -55,33 +56,66 @@ public class DeviceStatusApiItem implements ViewApiItem {
@Override
public List<ViewFetchResult> fetch(List<ViewApiParams.Value> values, ViewApiParams params) {
if(StrUtil.isBlank(params.getRange())) {
throw new ServiceException("未指定统计范围配置");
}
if(StrUtil.isBlank(params.getCategory())) {
throw new ServiceException("未指定产品轴配置");
}
List<ViewFetchResult> results = new ArrayList<>(values.size());
values.stream().forEach(item -> {
if(Objects.equals("range", params.getCategory())) {
Map<String, ListFetchResult> maps = new LinkedHashMap<>();
values.stream().forEach(item -> {
final String status = item.getValueItem(1);
final String countType = item.getValueItem(2);
final String rangeConfig = item.getRangeValue();
if(StrUtil.isBlank(rangeConfig)) {
throw new ServiceException("未指定统计范围");
}
final String[] split = rangeConfig.split(DataItemOption.SPLIT);
String range = split[0]; String rangeValue = null;
if(split.length > 1) {
rangeValue = split[1];
}
final String status = item.getValueItem(1);
final String countType = item.getValueItem(2);
List<DeviceStatusCountDto> countDtos = isvDataService.countDeviceStatus(status
, params.getCategory(), params.getRange(), params.getRanges());
if(CollectionUtil.isNotEmpty(countDtos)) {
countDtos.forEach(countDto -> {
ListFetchResult listFetchResult = maps.get(item.getItem());
if(listFetchResult == null) {
maps.put(item.getItem(), listFetchResult = new ListFetchResult(item.getItem(), new ArrayList<>()));
}
DeviceStatusCountDto num = isvDataService.countDeviceStatus(status, range, rangeValue);
if("count".equals(countType)) {
results.add(new NumberFetchResult(item.getItem(), num.getTotal()));
} else if("ratio".equals(countType)) {
results.add(new NumberFetchResult(item.getItem()
, new BigDecimal(num.getValue() / (num.getTotal() * 1.0))
.setScale(2, BigDecimal.ROUND_DOWN)));
} else {
if("count".equals(countType)) {
listFetchResult.addValue(new BaseEchartsCount(countDto.getName(), countDto.getValue()));
} else if("ratio".equals(countType)) {
listFetchResult.addValue(new BaseEchartsCount(countDto.getName()
, new BigDecimal(countDto.getValue() / (countDto.getTotal() * 1.0))
.setScale(2, BigDecimal.ROUND_DOWN)));
} else {
listFetchResult.addValue(new BaseEchartsCount(countDto.getName(), countDto.getTotal()));
}
});
}
});
}
results.addAll(maps.values());
} else if(Objects.equals("time", params.getCategory())) {
throw new ServiceException("不支持按时间统计");
} else {
values.stream().forEach(item -> {
final String status = item.getValueItem(1);
final String countType = item.getValueItem(2);
List<DeviceStatusCountDto> countDtos = isvDataService.countDeviceStatus(status
, params.getCategory(), params.getRange(), params.getRanges());
final DeviceStatusCountDto countDto = countDtos.get(0);
if ("count".equals(countType)) {
results.add(new NumberFetchResult(item.getItem(), countDto.getValue()));
} else if ("ratio".equals(countType)) {
results.add(new NumberFetchResult(item.getItem()
, new BigDecimal(countDto.getValue() / (countDto.getTotal() * 1.0))
.setScale(2, BigDecimal.ROUND_DOWN)));
} else {
results.add(new NumberFetchResult(item.getItem(), countDto.getTotal()));
}
});
}
});
return results;
}
@@ -1,10 +1,8 @@
package com.iteaj.iboot.plugin.iotview.api;
import cn.hutool.core.collection.CollectionUtil;
import com.iteaj.framework.spi.iot.view.DataItemOption;
import com.iteaj.framework.spi.iot.view.ViewApiItem;
import com.iteaj.framework.spi.iot.view.ViewApiParams;
import com.iteaj.framework.spi.iot.view.ViewFetchResult;
import com.iteaj.framework.spi.iot.data.BaseEchartsCount;
import com.iteaj.framework.spi.iot.view.*;
import com.iteaj.iboot.plugin.iotview.service.ISVDataService;
import org.springframework.stereotype.Component;
@@ -48,7 +46,21 @@ public class ModelAttrApiItem implements ViewApiItem {
@Override
public List<ViewFetchResult> fetch(List<ViewApiParams.Value> values, ViewApiParams params) {
return null;
return Arrays.asList(new ListFetchResult("温度", Arrays.asList(
new BaseEchartsCount("2025-01", 30),
new BaseEchartsCount("2025-02", 50),
new BaseEchartsCount("2025-03", 70),
new BaseEchartsCount("2025-04", 90),
new BaseEchartsCount("2025-05", 88)
)
)
, new ListFetchResult("湿度", Arrays.asList(
new BaseEchartsCount("2025-01", 28),
new BaseEchartsCount("2025-02", 54),
new BaseEchartsCount("2025-03", 42),
new BaseEchartsCount("2025-04", 19),
new BaseEchartsCount("2025-05", 38)
)));
}
@Override
@@ -98,7 +98,11 @@ public class ISVDataController {
if(Objects.equals(args[0], "device")) {
List<DataItemOption> devices = isvDataService.listDeviceOptions(args[1]);
if(CollectionUtil.isNotEmpty(devices)) {
devices.forEach(item -> {
item.setValue(key + DataItemOption.SPLIT + item.getValue()).setLeaf(true);
});
return IotViewResult.Success(devices);
}
}
return IotViewResult.Success(Collections.EMPTY_LIST);
@@ -16,4 +16,9 @@ public class DeviceStatusCountDto {
* 总值
*/
private int total;
/**
* 类别名称
*/
private String name;
}
@@ -14,5 +14,11 @@ public interface ISVDataMapper extends Mapper {
List<DataItemOption> listGroupOption();
DeviceStatusCountDto countDeviceStatus(String status, String range, String rangeValue);
List<DeviceStatusCountDto> countDeviceStatus(String status, String range, List<String> values);
List<DataItemOption> listDeviceOptions(String productCode);
List<DeviceStatusCountDto> countDeviceStatusByTime(String status, String range, List<String> values);
List<DeviceStatusCountDto> countDeviceStatusByRange(String status, String range, List<String> values);
}
@@ -15,5 +15,5 @@ public interface ISVDataService {
List<DataItemOption> listDeviceOptions(String productCode);
DeviceStatusCountDto countDeviceStatus(String status, String range, String rangeValue);
List<DeviceStatusCountDto> countDeviceStatus(String status, String category, String range, List<String> values);
}
@@ -7,6 +7,7 @@ import com.iteaj.iboot.plugin.iotview.service.ISVDataService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
@Service
public class ISVDataServiceImpl implements ISVDataService {
@@ -34,11 +35,17 @@ public class ISVDataServiceImpl implements ISVDataService {
@Override
public List<DataItemOption> listDeviceOptions(String productCode) {
return null;
return isvDataMapper.listDeviceOptions(productCode);
}
@Override
public DeviceStatusCountDto countDeviceStatus(String status, String range, String rangeValue) {
return isvDataMapper.countDeviceStatus(status, range, rangeValue);
public List<DeviceStatusCountDto> countDeviceStatus(String status, String category, String range, List<String> values) {
if(Objects.equals(category, "time")) {
return isvDataMapper.countDeviceStatusByTime(status, range, values);
} else if(Objects.equals(category, "range")) {
return isvDataMapper.countDeviceStatusByRange(status, range, values);
} else { // void
return isvDataMapper.countDeviceStatus(status, range, values);
}
}
}
@@ -30,10 +30,68 @@
</select>
<select id="countDeviceStatus" resultType="com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto">
select count(if(status=#{status}, 1, null)) value, count(1) total from iot_device
<where>
</where>
select count(if(a.status=#{status}, 1, null)) value, count(1) total, b.name from iot_device a
<if test="range == 'device'">
left join iot_device b on a.id=b.id
where uid in (
<foreach collection="values" separator="," item="uid">
#{uid}
</foreach>
)
</if>
<if test="range == 'product'">
right join iot_product b on a.product_id=b.id
where b.code in (
<foreach collection="values" separator="," item="productCode">
#{productCode}
</foreach>
)
</if>
<if test="range == 'group'">
right join iot_device_group b on a.device_group_id=b.id
where b.id in (
<foreach collection="values" separator="," item="groupId">
#{groupId}
</foreach>
)
</if>
</select>
<select id="listDeviceOptions" resultMap="BaseResultMap">
select a.name label, a.uid code from iot_device a
right join iot_product p on a.product_id = p.id
where p.code = #{productCode}
</select>
<select id="countDeviceStatusByTime" resultType="com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto">
select count(if(a.status=#{status}, 1, null)) value, count(1) total from iot_device a
</select>
<select id="countDeviceStatusByRange" resultType="com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto">
select count(if(a.status=#{status}, 1, null)) value, count(1) total, b.name from iot_device a
<if test="range == 'device'">
left join iot_device b on a.id=b.id
where uid in (
<foreach collection="values" separator="," item="uid">
#{uid}
</foreach>
)
</if>
<if test="range == 'product'">
right join iot_product b on a.product_id=b.id
where b.code in (
<foreach collection="values" separator="," item="productCode">
#{productCode}
</foreach>
)
group by b.id
</if>
<if test="range == 'group'">
right join iot_device_group b on a.device_group_id=b.id
where b.id in (
<foreach collection="values" separator="," item="groupId">
#{groupId}
</foreach>
)
group by b.id
</if>
</select>
</mapper>