修复告警列表,新增0x11报警恢复,新增联动控制箱控制联动,优化设备导出,修增设备安装记录

master
小鱼干 3 weeks ago
parent 24971d96a4
commit b9346d635a

@ -0,0 +1,83 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.model.alert;
import cc.iotkit.model.Owned;
import cc.iotkit.model.TenantModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AlertRecordBo extends TenantModel implements Owned<Long> {
private Long id;
/**
*
*/
private String uid;
/**
*
*/
private String name;
/**
* 1-5
*/
private String level;
/**
*
*/
/* @JsonFormat(timezone = "Asia/Shanghai",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")*/
private Long alertTime;
private String alertTimeStats;
/**
*
*/
private String details;
private Long tenantId;
private Long deptAreaId;
/**
*
*/
private Boolean readFlg;
private Boolean statusFlg = false;
/* @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
public Date getAlertTime() {
return new Date(this.alertTime);
}*/
}

@ -72,4 +72,5 @@ public class DeviceDetectorInfo extends TenantModel implements Owned<String>,Ser
private String node;
private String gasTypeKey;
private String dataDetectorValue;
private String nodeContext;
}

@ -45,7 +45,9 @@ public class DeviceInfo extends TenantModel implements Owned<String> {
private String deviceId;
private String site;
private String longitude;
private String latitude;
private String name;
private String signalStrength;
private String deviceVersion;
@ -95,7 +97,9 @@ public class DeviceInfo extends TenantModel implements Owned<String> {
private String nodeThreeDevice;
private String nodeFourDevice;
private String nodeFiveDevice;
private String nodeStatus;
private String node;
private String nodeDevice;
/**
* ID
*/

@ -94,4 +94,11 @@ public class DeviceInstallInfo extends TenantModel implements Owned<String>,Seri
// @ApiModelProperty(value = "装电源线照片")
private String fiexImage;
private Integer state;
//@ExcelProperty(value = "厂家")
private String manufacturer;
//@ExcelProperty(value = "安装情况")
private String position;
private String site;
//绑定人电话
private String bindUserIpone;
}

@ -33,6 +33,8 @@ import java.util.List;
public interface IAlertConfigData extends ICommonData<AlertConfig, Long> {
List<AlertConfig> findByUidAndRuleInfoId(String uid, String ruleInfoId);
List<AlertConfig> findByRuleInfoId(String ruleInfoId);
List<AlertConfig> findByDeviceName(String deviceName);
List<AlertConfig> findByUidAndRuleInfoIdAndDeviceName(String uid, String ruleInfoId,String deviceName);
Paging<AlertConfig> selectAlertConfigPage(PageRequest<AlertConfig> request);

@ -26,6 +26,7 @@ import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.data.ICommonData;
import cc.iotkit.model.alert.AlertRecord;
import cc.iotkit.model.alert.AlertRecordBo;
import cc.iotkit.model.stats.AlertStatDTO;
import java.util.List;
@ -36,6 +37,7 @@ public interface IAlertRecordData extends ICommonData<AlertRecord, Long> {
Paging<AlertRecord> selectAlertConfigPage(PageRequest<AlertRecord> request);
List<AlertRecord> selectAlertConfigPage(AlertRecordBo request);
List<AlertStatDTO> getAlertRecord();

@ -116,10 +116,17 @@ public interface IDeviceInfoData extends IOwnedData<DeviceInfo, String> {
*/
Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey,
String groupId, Boolean online, String keyword,
int page, int size,Long areaDepeId);
int page, int size,Long areaDepeId,String startTime,String endTime);
Paging<DeviceInfo> findByConditionsExcel(String name,String uid, String subUid, String productKey,
String groupId, Boolean online, String keyword,
int page, int size,Long areaDepeId,String startTime,String endTime);
Paging<DeviceInfo> findByConditions1(String name,String uid, String subUid, String productKey,
String groupId, Boolean online, String keyword,
int page, int size,Long areaDepeId);
int page, int size,Long areaDepeId,String startTime,String endTime);
/**
*
*

@ -34,6 +34,8 @@ public interface IUserInfoData extends ICommonData<UserInfo, Long> {
UserInfo findByUid(String uid);
UserInfo findByUidAndUserName(String uid,String userName);
UserInfo findByUserName(String userName);
List<UserInfo> findByUserNameLike(String userName);
List<UserInfo> findByType(int type);
Paging<UserInfo> findAll(PageRequest<UserInfo> pageRequest);
}

@ -231,12 +231,19 @@ public class DeviceInfoDataCache implements IDeviceInfoData, SmartInitializingSi
@Override
public Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey,
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId);
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId,startTime,endTime);
}
@Override
public Paging<DeviceInfo> findByConditionsExcel(String name,String uid, String subUid, String productKey,
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditionsExcel(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId,startTime,endTime);
}
public Paging<DeviceInfo> findByConditions1(String name,String uid, String subUid, String productKey,
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId) {
return deviceInfoData.findByConditions1(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId);
String groupId, Boolean state, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditions1(name,uid, subUid, productKey, groupId, state, keyword, page, size,deptAreaId,startTime,endTime);
}
@Override
public void updateTag(String deviceId, DeviceInfo.Tag tag) {

@ -187,12 +187,17 @@ public class DeviceInfoPropertyDataCache implements IDeviceInfoData {
}
@Override
public Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId);
public Paging<DeviceInfo> findByConditions(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId,startTime,endTime);
}
@Override
public Paging<DeviceInfo> findByConditions1(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId);
public Paging<DeviceInfo> findByConditionsExcel(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditionsExcel(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId,startTime,endTime);
}
@Override
public Paging<DeviceInfo> findByConditions1(String name,String uid, String subUid, String productKey, String groupId, Boolean online, String keyword, int page, int size,Long deptAreaId,String startTime,String endTime) {
return deviceInfoData.findByConditions(name,uid, subUid, productKey, groupId, online, keyword, page, size,deptAreaId,startTime, endTime);
}
@Override
public void updateTag(String deviceId, DeviceInfo.Tag tag) {

@ -74,6 +74,10 @@ public class UserInfoDataCache implements IUserInfoData {
public UserInfo findByUserName(String userName) {
return userInfoData.findByUserName(userName);
}
@Override
public List<UserInfo> findByUserNameLike(String userName) {
return userInfoData.findByUserNameLike(userName);
}
@Override
public List<UserInfo> findByIds(Collection<Long> id) {

@ -38,5 +38,7 @@ import java.util.List;
public interface AlertConfigRepository extends JpaRepository<TbAlertConfig, Long>, QuerydslPredicateExecutor<TbAlertConfig> {
List<TbAlertConfig> findByUidAndRuleInfoId(String uid, String ruleInfoId);
List<TbAlertConfig> findByUidAndRuleInfoIdAndDeviceName(String uid, String ruleInfoId,String deviceName);
List<TbAlertConfig> findByRuleInfoIdAndEnable(String ruleInfoId,Boolean enable);
List<TbAlertConfig> findByDeviceNameAndEnable(String deviceName,Boolean enable);
List<TbAlertConfig> findByUidAndRuleInfoIdAndDeviceNameAndEnable(String uid, String ruleInfoId,String deviceName,Boolean enable);
}

@ -33,7 +33,7 @@ public interface DeviceGroupMappingRepository extends JpaRepository<TbDeviceGrou
List<TbDeviceGroupMapping> findByDeviceId(String deviceId);
TbDeviceGroupMapping findByDeviceIdAndGroupId(String deviceId, String groupId);
TbDeviceGroupMapping findByDeviceIdAndGroupIdAndTenantId(String deviceId, String groupId,Long tenantId);
long countByGroupId(String groupId);

@ -34,7 +34,7 @@ public interface UserInfoRepository extends JpaRepository<TbUserInfo, String>, Q
TbUserInfo findByUid(String uid);
TbUserInfo findByUidAndUserName(String uid,String userName);
TbUserInfo findByUserName(String userName);
List<TbUserInfo> findByUserNameLike(String userName);
List<TbUserInfo> findByType(int type);
}

@ -74,4 +74,5 @@ public class TbDeviceDetectorInfo extends BaseEntity implements TenantAware {
private String node;
private String gasTypeKey;
private String dataDetectorValue;
private String nodeContext;
}

@ -87,14 +87,28 @@ public class AlertConfigDataImpl implements IAlertConfigData, IJPACommData<Alert
return MapstructUtils.convert(alertConfigRepository.findByUidAndRuleInfoId(uid, ruleInfoId), AlertConfig.class);
// return new Paging<>(alertConfigPage.getTotalElements(), MapstructUtils.convert(alertConfigPage.getContent(), AlertConfig.class));
}
@Override
public List<AlertConfig> findByRuleInfoId(String ruleInfoId) {
return MapstructUtils.convert(alertConfigRepository.findByRuleInfoIdAndEnable(ruleInfoId,true), AlertConfig.class);
// return new Paging<>(alertConfigPage.getTotalElements(), MapstructUtils.convert(alertConfigPage.getContent(), AlertConfig.class));
}
@Override
public List<AlertConfig> findByDeviceName(String deviceName) {
return MapstructUtils.convert(alertConfigRepository.findByDeviceNameAndEnable(deviceName,true), AlertConfig.class);
// return new Paging<>(alertConfigPage.getTotalElements(), MapstructUtils.convert(alertConfigPage.getContent(), AlertConfig.class));
}
@Override
public List<AlertConfig> findByUidAndRuleInfoIdAndDeviceName(String uid, String ruleInfoId, String deviceName) {
return MapstructUtils.convert(alertConfigRepository.findByUidAndRuleInfoIdAndDeviceName(uid, ruleInfoId,deviceName), AlertConfig.class);
return MapstructUtils.convert(alertConfigRepository.findByUidAndRuleInfoIdAndDeviceNameAndEnable(uid, ruleInfoId,deviceName,true), AlertConfig.class);
// return new Paging<>(alertConfigPage.getTotalElements(), MapstructUtils.convert(alertConfigPage.getContent(), AlertConfig.class));
}
private Predicate buildQueryCondition(AlertConfig dictData) {
return PredicateBuilder.instance()
.and(ObjectUtil.isNotNull(dictData.getMessagePush()), () -> tbAlertConfig.messagePush.like("%" + dictData.getMessagePush() +"%"))
.and(ObjectUtil.isNotNull(dictData.getDeviceName()), () -> tbAlertConfig.deviceName.like("%" + dictData.getDeviceName() +"%"))
.and(dictData.getUid() != null, () -> tbAlertConfig.uid.eq(AuthUtil.getUserId())).build();
}
}

@ -37,9 +37,12 @@ import cc.iotkit.data.model.QTbAlertRecord;
import cc.iotkit.data.model.TbAlertRecord;
import cc.iotkit.data.util.PageBuilder;
import cc.iotkit.data.util.PredicateBuilder;
import cc.iotkit.model.alert.AlertConfig;
import cc.iotkit.model.alert.AlertRecord;
import cc.iotkit.model.alert.AlertRecordBo;
import cc.iotkit.model.stats.AlertStatDTO;
import cc.iotkit.model.system.SysLoginInfo;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Predicate;
@ -63,6 +66,8 @@ import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static cc.iotkit.data.model.QTbAlertRecord.tbAlertRecord;
@ -171,6 +176,43 @@ public class AlertRecordDataImpl implements IAlertRecordData, IJPACommData<Alert
return new Paging<>(results.getTotal(), results.getResults()).to(AlertRecord.class);
}
private String extractByPattern(String text, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
return matcher.find() ? matcher.group(1) : null;
}
@Override
public List<AlertRecord> selectAlertConfigPage(AlertRecordBo request) {
LocalDateTime endDateTime = LocalDateTime.now();
LocalDateTime beginDateTime = endDateTime.minusMinutes(10);
// LocalDateTime beginDateTime = LocalDateTime.parse(beginTime, formatter);
// LocalDateTime endDateTime = LocalDateTime.parse(endTime, formatter);
// 提取设备ID
String deviceId = extractByPattern(request.getDetails(), "设备【(.*?)】");
System.out.println("设备ID:" + deviceId);
// 提取事件类型
String eventType = extractByPattern(request.getDetails(), "类型为:【(.*?)】");
System.out.println("事件类型:" + eventType);
long beginMillis = beginDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
long endMillis = endDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
QueryResults<TbAlertRecord> results = jpaQueryFactory.selectFrom(tbAlertRecord)
.where(PredicateBuilder.instance()
.and(tbAlertRecord.alertTime.between(beginMillis, endMillis))
.and(ObjectUtil.isNotEmpty(deviceId),
() -> tbAlertRecord.details.like( deviceId + "%") )
.and(ObjectUtil.isNotEmpty(eventType),
() -> tbAlertRecord.details.like(eventType + "%") ).build())
.orderBy(tbAlertRecord.id.desc())
.fetchResults();
return MapstructUtils.convert(results.getResults(), AlertRecord.class);
// return new Paging<>(results.getTotal(), results.getResults()).to(AlertRecord.class);
}
private static Predicate genTimePredicate(Map params) {
/* DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate beginDate = LocalDate.parse(params.get("beginTime").toString(), formatter);

@ -69,6 +69,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
@ -80,6 +81,7 @@ import java.util.stream.Collectors;
import static cc.iotkit.data.model.QTbAlertRecord.tbAlertRecord;
import static cc.iotkit.data.model.QTbDeviceGroupMapping.tbDeviceGroupMapping;
import static cc.iotkit.data.model.QTbDeviceInfo.tbDeviceInfo;
import static cc.iotkit.data.model.QTbDeviceInstallInfo.tbDeviceInstallInfo;
import static cc.iotkit.data.model.QTbDeviceSubUser.tbDeviceSubUser;
import static cc.iotkit.data.model.QTbProduct.tbProduct;
import static cc.iotkit.data.model.QTbSysTenant.tbSysTenant;
@ -344,6 +346,8 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
private void parseStateToDto(TbDeviceInfo vo, DeviceInfo dto) {
dto.setState(new DeviceInfo.State("online".equals(vo.getState()),
vo.getOnlineTime(), vo.getOfflineTime()));
dto.setLatitude(vo.getLatitude());
dto.setLongitude(vo.getLongitude());
dto.setLocate(new DeviceInfo.Locate(vo.getLongitude(), vo.getLatitude()));
}
@ -490,10 +494,10 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
}
@Override
public Paging<DeviceInfo> findByConditions(String name, String uid, String subUid,
public Paging<DeviceInfo> findByConditionsExcel(String name, String uid, String subUid,
String productKey, String groupId,
Boolean online, String keyword,
int page, int size, Long deptAreaId) {
int page, int size, Long deptAreaId,String startTime,String endTime) {
JPAQuery<TbDeviceInfo> query = jpaQueryFactory.selectFrom(tbDeviceInfo);
// 根据groupId, 如果groupId存在则关联查询TbDeviceGroupMapping, 根据groupId,查询对应的devices
@ -567,7 +571,125 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%")
.or(tbDeviceInfo.deviceName.like("%" + keyword + "%")));
}
if (ObjectUtil.isNotNull(startTime)&& ObjectUtil.isNotNull(endTime)) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDateTime = sdf.parse(startTime);
Date dateTime = sdf.parse(endTime);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime startDateTime = LocalDateTime.parse(dictData.getStartTime() , formatter);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime dateTime = LocalDateTime.parse(dictData.getEndTime(), formatter);
query.where(tbDeviceInfo.createTime.between(startDateTime, dateTime));
} catch (Exception e) {
}
}
query.orderBy(tbDeviceInfo.createAt.desc());
// query.offset((page - 1) * size).limit(size);
List<TbDeviceInfo> tbDeviceInfos = query.fetch();
long total = query.fetchCount();
List<DeviceInfo> deviceInfos = new ArrayList<>(tbDeviceInfos.size());
for (TbDeviceInfo tbDeviceInfo : tbDeviceInfos) {
DeviceInfo deviceInfo = MapstructUtils.convert(tbDeviceInfo, DeviceInfo.class);
// fillDeviceInfo(tbDeviceInfo.getDeviceId(), tbDeviceInfo, deviceInfo);
deviceInfos.add(deviceInfo);
}
return new Paging<>(total, deviceInfos);
}
@Override
public Paging<DeviceInfo> findByConditions(String name, String uid, String subUid,
String productKey, String groupId,
Boolean online, String keyword,
int page, int size, Long deptAreaId,String startTime,String endTime) {
JPAQuery<TbDeviceInfo> query = jpaQueryFactory.selectFrom(tbDeviceInfo);
// 根据groupId, 如果groupId存在则关联查询TbDeviceGroupMapping, 根据groupId,查询对应的devices
if (StringUtils.isNotBlank(groupId)) {
query.join(tbDeviceGroupMapping).on(tbDeviceGroupMapping.deviceId.eq(tbDeviceInfo.deviceId));
query.where(tbDeviceGroupMapping.groupId.eq(groupId));
}
if (StringUtils.isNotBlank(uid)) {
query.where(tbDeviceInfo.uid.eq(uid));
}
if (StringUtils.isNotBlank(name)) {
query.where(tbDeviceInfo.name.like("%" + name + "%"));
}
System.out.println(TenantHelper.getTenantId());
if (ObjectUtil.isNotNull(TenantHelper.getTenantId()) && (!LoginHelper.isSuperAdmin() || TenantHelper.getTenantId()!=0)) {
query.where(tbDeviceInfo.tenantId.eq(TenantHelper.getTenantId()));
}
if (ObjectUtil.isNotNull(deptAreaId)) {
List<Long> areaIds;
// if (Objects.nonNull(user) && Objects.nonNull(user.getDeptAreaId())) {
Long areaId = deptAreaId;
List<SysDept> depts = sysDeptData.findByDeptId(areaId);
areaIds = StreamUtils.toList(depts, SysDept::getId);
areaIds.add(areaId);
if (ObjectUtil.isNotEmpty(areaIds)) {
query.where(tbDeviceInfo.deptAreaId.in(areaIds));
}
}else{
if(!LoginHelper.isSuperAdmin()) {
if(ObjectUtil.isNotEmpty(LoginHelper.getUserId())) {
SysUser user = isSysUserData.findById(LoginHelper.getUserId());
if (ObjectUtil.isNotNull(user)) {
if (ObjectUtil.isNotNull(user.getDeptAreaId())) {
List<Long> areaIds;
// if (Objects.nonNull(user) && Objects.nonNull(user.getDeptAreaId())) {
Long areaId = user.getDeptAreaId();
List<SysDept> depts = sysDeptData.findByDeptId(areaId);
areaIds = StreamUtils.toList(depts, SysDept::getId);
areaIds.add(areaId);
if (ObjectUtil.isNotEmpty(areaIds)) {
query.where(tbDeviceInfo.deptAreaId.in(areaIds));
}
} else {
if(ObjectUtil.isNotEmpty(LoginHelper.getUserType()) && !LoginHelper.getUserType().equals(UserType.APP_USER)) {
//没有绑定区域查不到设备
query.where(tbDeviceInfo.id.eq("0"));
}
}
}
}
}else{
query.where(tbDeviceInfo.deptAreaId.isNull());
}
}
if (StringUtils.isNotBlank(subUid)) {
query.join(tbDeviceSubUser).on(tbDeviceSubUser.deviceId.eq(tbDeviceInfo.deviceId));
query.where(tbDeviceSubUser.uid.eq(subUid));
}
if (StringUtils.isNotBlank(productKey)) {
query.where(tbDeviceInfo.productKey.eq(productKey));
}
if (online != null) {
query.where(tbDeviceInfo.state.eq(online ? "online" : "offline"));
}
if (StringUtils.isNotBlank(keyword)) {
query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%")
.or(tbDeviceInfo.deviceName.like("%" + keyword + "%")));
}
if (ObjectUtil.isNotNull(startTime)&& ObjectUtil.isNotNull(endTime)) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDateTime = sdf.parse(startTime);
Date dateTime = sdf.parse(endTime);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime startDateTime = LocalDateTime.parse(dictData.getStartTime() , formatter);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime dateTime = LocalDateTime.parse(dictData.getEndTime(), formatter);
query.where(tbDeviceInfo.createTime.between(startDateTime, dateTime));
} catch (Exception e) {
}
}
query.orderBy(tbDeviceInfo.createAt.desc());
query.offset((page - 1) * size).limit(size);
@ -585,7 +707,7 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
public Paging<DeviceInfo> findByConditions1(String name, String uid, String subUid,
String productKey, String groupId,
Boolean online, String keyword,
int page, int size, Long deptAreaId) {
int page, int size, Long deptAreaId,String startTime,String endTime) {
JPAQuery<TbDeviceInfo> query = jpaQueryFactory.selectFrom(tbDeviceInfo);
// 根据groupId, 如果groupId存在则关联查询TbDeviceGroupMapping, 根据groupId,查询对应的devices
@ -642,7 +764,20 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%")
.or(tbDeviceInfo.deviceName.like("%" + keyword + "%")));
}
if (ObjectUtil.isNotNull(startTime)&& ObjectUtil.isNotNull(endTime)) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDateTime = sdf.parse(startTime);
Date dateTime = sdf.parse(endTime);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime startDateTime = LocalDateTime.parse(dictData.getStartTime() , formatter);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime dateTime = LocalDateTime.parse(dictData.getEndTime(), formatter);
query.where(tbDeviceInfo.createTime.between(startDateTime, dateTime));
} catch (Exception e) {
}
}
query.orderBy(tbDeviceInfo.createAt.desc());
query.offset((page - 1) * size).limit(size);
@ -971,14 +1106,14 @@ public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceI
//设备分组转换
Map<String, DeviceInfo.Group> groupMap = data.getGroup();
groupMap.forEach((id, group) -> {
TbDeviceGroupMapping mapping = deviceGroupMappingRepository.findByDeviceIdAndGroupId(data.getDeviceId(), id);
TbDeviceGroupMapping mapping = deviceGroupMappingRepository.findByDeviceIdAndGroupIdAndTenantId(data.getDeviceId(), id,data.getTenantId());
if (mapping == null) {
//保存设备分组与设备对应关系
deviceGroupMappingRepository.save(new TbDeviceGroupMapping(
UUID.randomUUID().toString(),
data.getDeviceId(),
id,
TenantHelper.getTenantId()
data.getTenantId()
));
}
});

@ -79,6 +79,10 @@ public class UserInfoDataImpl implements IUserInfoData, IJPACommData<UserInfo, L
public UserInfo findByUserName(String userName) {
return MapstructUtils.convert(userInfoRepository.findByUserName(userName), UserInfo.class);
}
@Override
public List<UserInfo> findByUserNameLike(String userName) {
return MapstructUtils.convert(userInfoRepository.findByUserNameLike(userName), UserInfo.class);
}
@Override
public List<UserInfo> findByType(int type) {

@ -45,6 +45,8 @@ public class TbThingModelMessage {
private String type;
private Integer deviceStatus;
private String identifier;
private int code;

@ -80,7 +80,7 @@ public class ThingModelMessageDataImpl implements IThingModelMessageData {
return new Paging<>(count, ruleLogs.stream().map(r ->
new ThingModelMessage(r.getTime().toString(), r.getMid(),
deviceId, r.getProductKey(), r.getDeviceName(),
r.getUid(), r.getType(), r.getIdentifier(), r.getCode(),
r.getUid(), r.getType(),r.getIdentifier(),r.getDeviceStatus(), r.getCode(),
JsonUtils.parseObject(r.getData(), Map.class),
r.getTime(), r.getReportTime()))
.collect(Collectors.toList()));
@ -120,7 +120,7 @@ public class ThingModelMessageDataImpl implements IThingModelMessageData {
return new Paging<>(count, ruleLogs.stream().map(r ->
new ThingModelMessage(r.getTime().toString(), r.getMid(),
r.getDeviceId(), r.getProductKey(), r.getDeviceName(),
r.getUid(), r.getType(), r.getIdentifier(), r.getCode(),
r.getUid(), r.getType(), r.getIdentifier(),r.getDeviceStatus(), r.getCode(),
JsonUtils.parseObject(r.getData(), Map.class),
r.getTime(), r.getReportTime()))
.collect(Collectors.toList()));

@ -2,12 +2,10 @@ package cc.iotkit.manager.config;
import cc.iotkit.model.device.DeviceInstallInfo;
import cn.hutool.core.util.ObjectUtil;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
@ -15,11 +13,11 @@ import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static cc.iotkit.manager.config.PDFUtils.drawAlignedText;
public class PDFGenerator {
// 1. 表格参数配置
@ -37,9 +35,9 @@ public class PDFGenerator {
public static void generateInstallationPDF(DeviceInstallInfo entity, OutputStream outputStream) throws IOException {
try (PDDocument document = new PDDocument()) {
// 加载字体(需替换实际路径)
//PDType0Font font = PDType0Font.load(document, new File("D:\\simsun.ttf"));
PDType0Font font = PDType0Font.load(document, new File("/ttf/simsun.ttf"));
// PDType0Font font = PDType0Font.load(document, new File("D:\\NotoSansCJK-Regular.ttf"));
//PDType0Font font = PDType0Font.load(document, new File("/ttf/simsun.ttf"));
PDType0Font font = PDType0Font.load(document, new File("/ttf/NotoSansCJK-Regular.ttf"));
// 初始化第一页
PDPage currentPage = new PDPage(PDRectangle.A4);
document.addPage(currentPage);
@ -55,7 +53,7 @@ public class PDFGenerator {
// 2. 绘制基本信息表格
String[][] baseData = {
// {"公司名称", entity.getCorporateName()},
// {"公司名称", entity.getCorporateName()},
{"申请时间", entity.getProposerTime().toString()},
{"申请人", entity.getProposer()},
{"申请人班组", entity.getProposerTeam()},
@ -74,7 +72,7 @@ public class PDFGenerator {
currentY -= (ROW_HEIGHT * baseData.length) + 20f;
// @ApiModelProperty(value = "安装前图片")
// 创建后续页面 - 图片部分
// 图片处理(带自动分页)
// 图片处理(带自动分页)
// 图片处理(带自动分页)
List<String[]> imageGroups = Arrays.asList(
new String[]{entity.getBeforeInstallationImage(), "安装前图片"},
@ -99,7 +97,7 @@ public class PDFGenerator {
.collect(Collectors.toList());
if (!validUrls.isEmpty()) {
// float totalHeight = calculateTotalHeight(validUrls);
// float totalHeight = calculateTotalHeight(validUrls);
List<String> wrappedTitleLines = wrapText(title,LEFT_COL_WIDTH - 2 * CELL_PADDING);
float titleHeight = wrappedTitleLines.size() * LINE_HEIGHT;
// 计算图片组的自适应高度
@ -127,12 +125,12 @@ public class PDFGenerator {
} finally {
cs.close();
}
// document.save("D:/output.pdf");
// document.save("D:/output.pdf");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
outputStream.flush();
baos.writeTo(outputStream);
// document.save(outputStream);
// document.save(outputStream);
}
}
private static List<String> wrapText(String text, float maxWidth) {
@ -213,7 +211,7 @@ public class PDFGenerator {
return totalHeight;
}*/
private static float calculateAdjustedImagesHeight(PDDocument doc, List<String> imageUrls,
/* private static float calculateAdjustedImagesHeight(PDDocument doc, List<String> imageUrls,
float maxWidth, float maxHeight) throws IOException {
float totalHeight = 0;
float remainingHeight = maxHeight;
@ -242,85 +240,162 @@ public class PDFGenerator {
}
}
return totalHeight;
}
return totalHeight*imageUrls.size();
}*/
private static void drawImageGroup(PDPageContentStream cs, PDDocument doc, PDType0Font font,
List<String> titleLines, List<String> imageUrls,
float startY, float totalHeight) throws IOException {
// float currentImageY = startY - CELL_PADDING;
// 绘制单元格边框
cs.setLineWidth(0.5f);
cs.addRect(TABLE_MARGIN, startY - totalHeight, LEFT_COL_WIDTH, totalHeight);
cs.addRect(TABLE_MARGIN + LEFT_COL_WIDTH, startY - totalHeight, RIGHT_COL_WIDTH, totalHeight);
cs.stroke();
// 计算文本总高度
float textHeight = titleLines.size() * LINE_HEIGHT;
float textStartY = startY - (totalHeight / 2) + (textHeight / 2);
// 计算每张图片的可用高度(根据图片数量动态调整)
float imageAvailableHeight = totalHeight - 2 * CELL_PADDING;
float imageAvailableWidth = RIGHT_COL_WIDTH - 2 * CELL_PADDING;
if (imageUrls.size() == 1) {
// 单图片模式:一页两行,每行占半页高度
float singleImageHeight = imageAvailableHeight;
// 绘制标题(垂直居中)
float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
// 绘制第一行标题(顶部)
// float titleY = startY - CELL_PADDING - FONT_SIZE;
cs.beginText();
cs.setFont(font, FONT_SIZE);
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
for (String line : titleLines) {
cs.showText(line);
titleY -= LINE_HEIGHT;
cs.newLineAtOffset(0, -LINE_HEIGHT);
}
cs.endText();
// 在左侧单元格绘制标题(带自动换行)
cs.beginText();
cs.setFont(font, FONT_SIZE);
for (String line : titleLines) {
// 检查文本是否超出单元格宽度
/* float textWidth = font.getStringWidth(line) / 1000 * FONT_SIZE;
if (textWidth > LEFT_COL_WIDTH - 2*CELL_PADDING) {
line = TextUtils.truncateWithEllipsis(line, font,LEFT_COL_WIDTH - 2*CELL_PADDING);
}*/
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, textStartY);
cs.showText(line);
textStartY -= LINE_HEIGHT;
}
cs.endText();
float availableWidth = RIGHT_COL_WIDTH - 2 * CELL_PADDING;
float remainingHeight = totalHeight - 2 * CELL_PADDING;
// 在右侧单元格绘制图片
float currentImageY = startY - 10;
for (String url : imageUrls) {
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(url).openStream().readAllBytes(), "embedded-image");
// 计算图片的缩放比例
float scale = Math.min(
availableWidth / image.getWidth(),
remainingHeight / image.getHeight()
// 绘制第一行图片(自动缩放)
PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
float scale1 = Math.min(
imageAvailableWidth / image1.getWidth(),
singleImageHeight / image1.getHeight()
);
// 确保图片高度不小于最小值
float scaledHeight = Math.max(
image.getHeight() * scale,
MIN_IMAGE_HEIGHT
float scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
} else if (imageUrls.size() == 2) {
// 双图片模式:改为上下布局
float imageHeightPer = (imageAvailableHeight - CELL_PADDING) / 2;
// 绘制标题(垂直居中)
float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
cs.beginText();
cs.setFont(font, FONT_SIZE);
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
for (String line : titleLines) {
cs.showText(line);
titleY -= LINE_HEIGHT;
cs.newLineAtOffset(0, -LINE_HEIGHT);
}
cs.endText();
// 绘制第一张图片(上)
PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
float scale1 = Math.min(
imageAvailableWidth / image1.getWidth(),
imageHeightPer / image1.getHeight()
);
float scaledWidth = image.getWidth() * scale;
cs.drawImage(image,
float scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
currentImageY - scaledHeight,
scaledWidth, scaledHeight);
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
// 绘制第二张图片(下)
PDImageXObject image2 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(1)).openStream().readAllBytes(), "embedded-image");
float scale2 = Math.min(
imageAvailableWidth / image2.getWidth(),
imageHeightPer / image2.getHeight()
);
float scaledHeight2 = image2.getHeight() * scale2;
float scaledWidth2 = image2.getWidth() * scale2;
currentImageY -= scaledHeight + CELL_PADDING;
remainingHeight -= scaledHeight + CELL_PADDING;
cs.drawImage(image2,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1 - CELL_PADDING - scaledHeight2,
scaledWidth2, scaledHeight2);
/* // 双图片模式:一行并列显示
float imageWidthPer = (imageAvailableWidth - CELL_PADDING) / 2;
if (remainingHeight <= 0) {
break; // 超出可用高度则停止绘制
// 绘制标题(垂直居中)
float titleY = startY - totalHeight/2 + (titleLines.size() * LINE_HEIGHT)/2;
cs.beginText();
cs.setFont(font, FONT_SIZE);
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, titleY);
for (String line : titleLines) {
cs.showText(line);
titleY -= LINE_HEIGHT;
cs.newLineAtOffset(0, -LINE_HEIGHT);
}
cs.endText();
/* float imageWidth = RIGHT_COL_WIDTH - 10;
float height = imageWidth * image.getHeight() / image.getWidth();
// 绘制第一张图片(左)
PDImageXObject image1 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(0)).openStream().readAllBytes(), "embedded-image");
float scale1 = Math.min(
imageWidthPer / image1.getWidth(),
imageAvailableHeight / image1.getHeight()
);
float scaledHeight1 = image1.getHeight() * scale1;
float scaledWidth1 = image1.getWidth() * scale1;
cs.drawImage(image,
TABLE_MARGIN + LEFT_COL_WIDTH + 5,
currentImageY - height,
imageWidth, height);
cs.drawImage(image1,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
startY - CELL_PADDING - scaledHeight1,
scaledWidth1, scaledHeight1);
// 绘制第二张图片(右)
PDImageXObject image2 = PDImageXObject.createFromByteArray(doc,
new URL(imageUrls.get(1)).openStream().readAllBytes(), "embedded-image");
float scale2 = Math.min(
imageWidthPer / image2.getWidth(),
imageAvailableHeight / image2.getHeight()
);
float scaledHeight2 = image2.getHeight() * scale2;
float scaledWidth2 = image2.getWidth() * scale2;
currentImageY -= height + 10;*/
cs.drawImage(image2,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING + imageWidthPer + CELL_PADDING,
startY - CELL_PADDING - scaledHeight2,
scaledWidth2, scaledHeight2);*/
}
}
private static float calculateAdjustedImagesHeight(PDDocument doc, List<String> imageUrls,
float maxWidth, float maxHeight) throws IOException {
if (imageUrls.isEmpty()) return 0;
// return maxHeight;
if (imageUrls.size() == 1) {
// 单图片模式:占用半页高度
return maxHeight / 2;
} else {
// 双图片模式:整页高度
return maxHeight;
}
}
// 截断超长文本
private static String truncateText(PDType0Font font,String text, float maxWidth) throws IOException {
// PDType0Font font = ...; // 获取字体对象
// PDType0Font font = ...; // 获取字体对象
StringBuilder sb = new StringBuilder();
float currentWidth = 0;

@ -0,0 +1,703 @@
package cc.iotkit.manager.config;
import cc.iotkit.model.device.DeviceInstallInfo;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PDFGenerator22 {
// 1. 表格参数配置
// 参数配置(优化后)
private static final float FONT_SIZE = 11f;
private static final float ROW_HEIGHT = 35f;
private static final float TABLE_MARGIN = 50f;
private static final float LEFT_COL_WIDTH = 130f;
private static final float RIGHT_COL_WIDTH = 350f;
private static final float LINE_HEIGHT = FONT_SIZE * 1.2f;
private static final float CELL_PADDING = 5;
private static final float[] COLUMN_WIDTHS = {LEFT_COL_WIDTH, RIGHT_COL_WIDTH};
private static final float MIN_IMAGE_HEIGHT = 50;
public static void generateInstallationPDF(DeviceInstallInfo entity, OutputStream outputStream) throws IOException {
try (PDDocument document = new PDDocument()) {
// 加载字体(需替换实际路径)
PDType0Font font = PDType0Font.load(document, new File("D:\\simsun.ttf"));
// PDType0Font font = PDType0Font.load(document, new File("/ttf/simsun.ttf"));
// 初始化第一页
PDPage currentPage = new PDPage(PDRectangle.A4);
document.addPage(currentPage);
PDPageContentStream cs = new PDPageContentStream(document, currentPage);
float currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
try {
// 1. 绘制标题(居中)
drawCenteredText(cs, font, FONT_SIZE+10,
"安装信息录入表",
PDRectangle.A4.getWidth()/2, currentY);
currentY -= ROW_HEIGHT * 1.5f;
// 2. 绘制基本信息表格
String[][] baseData = {
// {"公司名称", entity.getCorporateName()},
{"申请时间", entity.getProposerTime().toString()},
{"申请人", entity.getProposer()},
{"申请人班组", entity.getProposerTeam()},
{"小区名字", entity.getCommunityName()},
{"用户姓名", entity.getUserName()},
{"电话", entity.getUserIpone()},
{"楼栋单元号", entity.getBuildingUnit()},
{"房间号", entity.getRoomNo()},
{"报警器编号", entity.getDeviceName()},
{"切断阀编号", entity.getShutValueNumber()},
{"燃气表号", entity.getGasMeterNumber()},
{"备注", entity.getBuildingUnit()}
};
drawTable(cs, font, TABLE_MARGIN, currentY, baseData, COLUMN_WIDTHS);
currentY -= (ROW_HEIGHT * baseData.length) + 20f;
// @ApiModelProperty(value = "安装前图片")
// 创建后续页面 - 图片部分
// 图片处理(带自动分页)
// 图片处理(带自动分页)
List<String[]> imageGroups = Arrays.asList(
new String[]{entity.getBeforeInstallationImage(), "安装前图片"},
new String[]{entity.getWorkingOfTheDetectorImage(), "安装完成探测器工作图片"},
new String[]{entity.getSideLeakageImage(), "测漏图片"},
new String[]{entity.getIgnitionPictureImage(), "点火图片"},
new String[]{entity.getInstallThePanoramicImage(), "安装完成全景图片"},
new String[]{entity.getOfGasMeterImage(), "燃气表图片"},
new String[]{entity.getWorkOrderImage(), "工单图片"},
new String[]{entity.getPunchingImage(), "打孔图片"},
new String[]{entity.getFiexImage(), "安装电源线图片"}
);
for (String[] group : imageGroups) {
String urls = group[0];
String title = group[1];
if (urls != null && !urls.trim().isEmpty()) {
List<String> validUrls = Arrays.stream(urls.split(","))
.map(String::trim)
.filter(url -> !url.isEmpty() && url.startsWith("http"))
.collect(Collectors.toList());
if (!validUrls.isEmpty()) {
// float totalHeight = calculateTotalHeight(validUrls);
List<String> wrappedTitleLines = wrapText(title,LEFT_COL_WIDTH - 2 * CELL_PADDING);
float titleHeight = wrappedTitleLines.size() * LINE_HEIGHT;
// 计算图片组的自适应高度
float imagesHeight = calculateAdjustedImagesHeight(document, validUrls,
RIGHT_COL_WIDTH - 2 * CELL_PADDING,
PDRectangle.A4.getHeight() - 2 * TABLE_MARGIN - titleHeight);
float totalHeight = Math.max(imagesHeight, titleHeight);
if (currentY < TABLE_MARGIN + Math.max(totalHeight, titleHeight)) {
cs.close();
currentPage = new PDPage(PDRectangle.A4);
document.addPage(currentPage);
cs = new PDPageContentStream(document, currentPage);
currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
}
drawImageGroup(cs, document, font, wrappedTitleLines, validUrls, currentY,
Math.max(totalHeight, titleHeight));
currentY -= Math.max(totalHeight, titleHeight);
}
}
}
} finally {
cs.close();
}
// document.save("D:/output.pdf");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
outputStream.flush();
baos.writeTo(outputStream);
// document.save(outputStream);
}
}
private static List<String> wrapText(String text, float maxWidth) {
List<String> lines = new ArrayList<>();
int maxCharsPerLine = (int)(maxWidth / (FONT_SIZE * 0.5f)); // 中文字符估算
StringBuilder currentLine = new StringBuilder();
for (String word : text.split("")) {
if (currentLine.length() + word.length() <= maxCharsPerLine) {
currentLine.append(word);
} else {
lines.add(currentLine.toString());
currentLine = new StringBuilder(word);
}
}
if (currentLine.length() > 0) {
lines.add(currentLine.toString());
}
return lines;
}
private static float calculateTotalHeight(List<String> imageUrls) throws IOException {
float totalHeight = 0;
for (String url : imageUrls) {
totalHeight += estimateImageHeight(url, RIGHT_COL_WIDTH - 10) + 10;
}
return totalHeight;
}
/* private static float calculateAdjustedImagesHeight(PDDocument doc, List<String> imageUrls,
float maxWidth, float maxHeight) throws IOException {
if (imageUrls.isEmpty()) return 0;
// 1. 预加载所有图片并收集尺寸信息
List<PDImageXObject> images = new ArrayList<>();
for (String url : imageUrls) {
try {
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(url).openStream().readAllBytes(), "embedded-image");
images.add(image);
} catch (IOException e) {
// 跳过加载失败的图片
continue;
}
}
// 2. 计算统一缩放比例
float uniformScale = Float.MAX_VALUE;
int validImageCount = images.size();
float availableHeightPerImage = (maxHeight - (validImageCount-1)*10f) / validImageCount; // 10为图片间距
for (PDImageXObject image : images) {
// 计算当前图片的最大允许缩放比例
float widthScale = maxWidth / image.getWidth();
float heightScale = availableHeightPerImage / image.getHeight();
float minScale = Math.min(widthScale, heightScale);
// 取所有图片中最小的缩放比例作为统一比例
uniformScale = Math.min(uniformScale, minScale);
}
// 3. 应用最小高度限制
uniformScale = Math.max(uniformScale, MIN_IMAGE_HEIGHT /
images.stream().map(img -> (float)img.getHeight()).max(Float::compare).orElse(1f));
// images.stream().mapToFloat(PDImageXObject::getHeight).max().orElse(1f));
// 4. 计算总高度(所有图片统一缩放后的高度 + 间距)
float totalHeight = 0;
for (PDImageXObject image : images) {
float scaledHeight = image.getHeight() * uniformScale;
totalHeight += scaledHeight + 10; // 10为图片间距
if (totalHeight > maxHeight) {
totalHeight -= scaledHeight + 10; // 移除超出的部分
break;
}
}
return totalHeight;
}*/
private static float calculateAdjustedImagesHeight(PDDocument doc, List<String> imageUrls,
float maxWidth, float maxHeight) throws IOException {
float totalHeight = 0;
float remainingHeight = maxHeight;
for (String url : imageUrls) {
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(url).openStream().readAllBytes(), "embedded-image");
// 计算图片的缩放比例
float scale = Math.min(
maxWidth / image.getWidth(),
remainingHeight / image.getHeight()
);
// 确保图片高度不小于最小值
float scaledHeight = Math.max(
image.getHeight() * scale,
MIN_IMAGE_HEIGHT
);
totalHeight += scaledHeight + 10; // 10是图片间距
remainingHeight -= scaledHeight + 10;
if (remainingHeight <= 0) {
break; // 超出可用高度则停止添加图片
}
}
return totalHeight*imageUrls.size();
}
private static void drawImageGroup(PDPageContentStream cs, PDDocument doc, PDType0Font font,
List<String> titleLines, List<String> imageUrls,
float startY, float totalHeight) throws IOException {
// float currentImageY = startY - CELL_PADDING;
// 绘制单元格边框
cs.setLineWidth(0.5f);
cs.addRect(TABLE_MARGIN, startY - totalHeight, LEFT_COL_WIDTH, totalHeight);
cs.addRect(TABLE_MARGIN + LEFT_COL_WIDTH, startY - totalHeight, RIGHT_COL_WIDTH, totalHeight);
cs.stroke();
// 计算文本总高度
float textHeight = titleLines.size() * LINE_HEIGHT;
float textStartY = 0f;
if(imageUrls.size() > 1){
textStartY = startY + startY/imageUrls.size() - (totalHeight / 2) + (textHeight / 2);
}else{
textStartY = startY - (totalHeight / 2) + (textHeight / 2);
}
// 在左侧单元格绘制标题(带自动换行)
cs.beginText();
cs.setFont(font, FONT_SIZE);
for (String line : titleLines) {
// 检查文本是否超出单元格宽度
/* float textWidth = font.getStringWidth(line) / 1000 * FONT_SIZE;
if (textWidth > LEFT_COL_WIDTH - 2*CELL_PADDING) {
line = TextUtils.truncateWithEllipsis(line, font,LEFT_COL_WIDTH - 2*CELL_PADDING);
}*/
cs.newLineAtOffset(TABLE_MARGIN + CELL_PADDING, textStartY);
cs.showText(line);
textStartY -= LINE_HEIGHT;
}
cs.endText();
float availableWidth = RIGHT_COL_WIDTH - 2 * CELL_PADDING;
float remainingHeight = totalHeight - 2 * CELL_PADDING;
// 在右侧单元格绘制图片
float currentImageY = startY - 10;
for (String url : imageUrls) {
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(url).openStream().readAllBytes(), "embedded-image");
// 计算图片的缩放比例
float scale = Math.min(
availableWidth / image.getWidth()/imageUrls.size(),
remainingHeight / image.getHeight()/imageUrls.size()
);
// 确保图片高度不小于最小值
float scaledHeight = Math.max(
image.getHeight() * scale,
MIN_IMAGE_HEIGHT
);
float scaledWidth = image.getWidth() * scale;
cs.drawImage(image,
TABLE_MARGIN + LEFT_COL_WIDTH + CELL_PADDING,
currentImageY - scaledHeight,
scaledWidth, scaledHeight);
currentImageY -= scaledHeight + CELL_PADDING;
remainingHeight -= scaledHeight + CELL_PADDING;
if (remainingHeight <= 0) {
break; // 超出可用高度则停止绘制
}
}
}
// 截断超长文本
private static String truncateText(PDType0Font font,String text, float maxWidth) throws IOException {
// PDType0Font font = ...; // 获取字体对象
StringBuilder sb = new StringBuilder();
float currentWidth = 0;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
float charWidth = font.getStringWidth(String.valueOf(c)) / 1000 * FONT_SIZE;
if (currentWidth + charWidth > maxWidth) {
break;
}
sb.append(c);
currentWidth += charWidth;
}
return sb.toString();
}
// 新增方法:计算文本高度(考虑换行)
private static float getTextHeight(String text, float maxWidth, PDType0Font font, float fontSize) throws IOException {
if (text == null || text.isEmpty()) {
return 0;
}
// 简单估算:假设每个中文字符宽度等于字体大小
int charsPerLine = (int)(maxWidth / fontSize);
int lineCount = (int)Math.ceil((double)text.length() / charsPerLine);
return lineCount * fontSize * 1.2f; // 行间距1.2倍
}
// 改进方法:绘制自动换行文本
private static void drawWrappedText(PDPageContentStream cs, PDType0Font font,
float fontSize, String text,
float startX, float startY, float maxWidth) throws IOException {
cs.setFont(font, fontSize);
cs.setLeading(fontSize * 1.2f); // 行间距
// 简单换行实现
int charsPerLine = (int)(maxWidth / (fontSize * 0.8)); // 中文字符估算
int pos = 0;
float currentY = startY;
while (pos < text.length()) {
int endPos = Math.min(pos + charsPerLine, text.length());
String line = text.substring(pos, endPos);
cs.beginText();
cs.newLineAtOffset(startX, currentY);
cs.showText(line);
cs.endText();
pos = endPos;
currentY -= fontSize * 1.2f;
}
}
// 图片高度预估方法
private static float estimateImageHeight(String imageUrl, float targetWidth) throws IOException {
try (InputStream is = new URL(imageUrl).openStream()) {
BufferedImage img = ImageIO.read(is);
return img.getHeight() * (targetWidth / img.getWidth());
}
}
/* public static void generateInstallationPDF(DeviceInstallInfo entity, OutputStream outputStream) throws IOException {
try (PDDocument document = new PDDocument()) {
// 加载中文字体需确保D:/simsun.ttc存在
PDType0Font font = PDType0Font.load(document, new File("D:\\simsun.ttf"));
// 创建单页文档
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
PDPageContentStream cs = new PDPageContentStream(document, page);
float currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
// 3. 绘制标题(居中)
drawCenteredText(cs, font, FONT_SIZE + 6,
"贵阳户内安装信息录入表",
PDRectangle.A4.getWidth() / 2, currentY);
currentY -= ROW_HEIGHT * 1.5f;
// 4. 基本信息表格
String[][] baseData = {
{"安装班组", entity.getProposerTeam()},
{"安装人", entity.getProposer()},
{"安装时间", entity.getProposerTime().toString()},
{"小区名称", entity.getCommunityName()},
{"楼栋号", entity.getBuildingUnit()},
{"单元号", entity.getBuildingUnit() != null ?
entity.getBuildingUnit().split("-")[0] : ""},
{"房号", entity.getRoomNo()},
{"用户姓名", entity.getUserName()},
{"联系方式", entity.getUserIpone()},
{"灶具类型", entity.getDeviceName() != null ?
(entity.getDeviceName().contains("台式") ? "台式灶" : "嵌入式灶") : ""}
};
drawTable(cs, font, TABLE_MARGIN, currentY, baseData,
new float[]{COLUMN_LEFT_WIDTH, COLUMN_WIDTH});
currentY -= (ROW_HEIGHT * baseData.length) + 20f;
// 5. 图片处理(内嵌到表格)
if (entity.getBeforeInstallationImage() != null) {
if (currentY < TABLE_MARGIN + 150) {
cs.close();
page = new PDPage(PDRectangle.A4);
document.addPage(page);
cs = new PDPageContentStream(document, page);
currentY = PDRectangle.A4.getHeight() - TABLE_MARGIN;
}
//page = new PDPage(PDRectangle.A4);
// document.addPage(page);
currentY = addImageRow(cs, document, font, "安装前图片",
entity.getBeforeInstallationImage(), TABLE_MARGIN, currentY);
// currentY -= ROW_HEIGHT * 3; // 图片行高是普通行的3倍
}
// 其他图片处理同理...
document.save("D:/output.pdf");
document.save(outputStream);
}
}*/
/* private static void drawTable(PDPageContentStream cs, PDType0Font font,
float x, float y, String[][] data, float[] colWidths) throws IOException {
// 计算表格总宽度
float tableWidth = 0;
for (float width : colWidths) tableWidth += width;
// 绘制外边框
cs.setLineWidth(1.5f);
cs.addRect(x, y - ROW_HEIGHT * data.length, tableWidth, ROW_HEIGHT * data.length);
cs.stroke();
// 绘制列线
float currentX = x;
for (int i = 0; i < colWidths.length - 1; i++) {
currentX += colWidths[i];
cs.moveTo(currentX, y);
cs.lineTo(currentX, y - ROW_HEIGHT * data.length);
cs.stroke();
}
// 绘制行线
for (int i = 1; i < data.length; i++) {
cs.moveTo(x, y - ROW_HEIGHT * i);
cs.lineTo(x + tableWidth, y - ROW_HEIGHT * i);
cs.stroke();
}
// 改进的文本定位
for (int row = 0; row < data.length; row++) {
for (int col = 0; col < data[row].length; col++) {
// 方案1手动求和推荐
float sum = 0;
for (int i = 0; i < col; i++) {
sum += colWidths[i];
}
String text = data[row][col] != null ? data[row][col] : "";
float textWidth = font.getStringWidth(text) / 1000 * FONT_SIZE;
float textX = x + sum
+ (colWidths[col] - textWidth)/2;
float textY = y - (row * ROW_HEIGHT) - (ROW_HEIGHT/2 - FONT_SIZE/4);
cs.beginText();
cs.newLineAtOffset(textX, textY);
cs.showText(text);
cs.endText();
}
}*/
// 填写内容(严格居中)
/* for (int row = 0; row < data.length; row++) {
currentX = x;
for (int col = 0; col < data[row].length; col++) {
String text = data[row][col] != null ? data[row][col] : "";
float textWidth = font.getStringWidth(text) / 1000 * FONT_SIZE;
cs.beginText();
cs.newLineAtOffset(
currentX + (colWidths[col] - textWidth) / 2,
y - (ROW_HEIGHT * row) - (ROW_HEIGHT / 2 + FONT_SIZE / 3)
);
cs.showText(text);
cs.endText();
currentX += colWidths[col];
}
}*/
private static void drawTable(PDPageContentStream cs, PDType0Font font,
float x, float y, String[][] data, float[] colWidths) throws IOException {
// 修改后的表格绘制代码
if (data == null || data.length == 0 || colWidths == null) return;
final float ROW_HEIGHT = 35f; // 增大行高以适应更大字体
final float FONT_SIZE = 14f; // 增大字体大小
final float PADDING = 5f;
// 计算表格总宽度
float tableWidth = 0;
for (float width : colWidths) {
tableWidth += width;
}
// 绘制表格边框和分隔线(保持不变)
cs.setLineWidth(1f);
cs.addRect(x, y - ROW_HEIGHT * data.length, tableWidth, ROW_HEIGHT * data.length);
cs.stroke();
// 绘制列分隔线
float currentX = x;
for (int i = 1; i < colWidths.length; i++) {
currentX += colWidths[i-1];
cs.moveTo(currentX, y);
cs.lineTo(currentX, y - ROW_HEIGHT * data.length);
cs.stroke();
}
// 绘制行分隔线
for (int i = 1; i <= data.length; i++) {
cs.moveTo(x, y - ROW_HEIGHT * i);
cs.lineTo(x + tableWidth, y - ROW_HEIGHT * i);
cs.stroke();
}
// 填写表格内容(关键修改部分)
cs.setFont(font, FONT_SIZE);
for (int row = 0; row < data.length; row++) {
currentX = x;
for (int col = 0; col < data[row].length; col++) {
String text = data[row][col] != null ? data[row][col] : "";
// 计算文本宽度
float textWidth = font.getStringWidth(text) / 1000 * FONT_SIZE;
float centerOffset = (colWidths[col] - textWidth) / 2;
// 修正垂直居中计算(关键修改)
float baselineOffset = (ROW_HEIGHT - FONT_SIZE) / 3; // 更精确的基线计算
cs.beginText();
cs.newLineAtOffset(
currentX + centerOffset,
y - (ROW_HEIGHT * row) - FONT_SIZE - baselineOffset // 修正垂直位置
);
cs.showText(text);
cs.endText();
currentX += colWidths[col];
}
}
}
private static float addImageRow(PDPageContentStream cs, PDDocument doc,
PDType0Font font, String title, String imageUrl,
float startX, float startY) throws IOException {
// 加载图片
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(imageUrl).openStream().readAllBytes(), "embedded-image");
// 动态计算尺寸
float imageWidth = RIGHT_COL_WIDTH - 10;
float scale = imageWidth / image.getWidth();
float imageHeight = image.getHeight() * scale;
float rowHeight = imageHeight + 20;
// 绘制单元格边框
cs.setLineWidth(0.5f);
cs.addRect(startX, startY - rowHeight, LEFT_COL_WIDTH, rowHeight);
cs.addRect(startX + LEFT_COL_WIDTH, startY - rowHeight, RIGHT_COL_WIDTH, rowHeight);
cs.stroke();
// 垂直居中文本(改进算法)
float textY = startY - rowHeight/2 + FONT_SIZE/2;
//String title = "安装完成探测器工作图片\n检测时间2025-08-14";
/* if(title.contains("\n")){
String[] lines = title.split("\n");
textY = startY - rowHeight/2 + FONT_SIZE/2 + (lines.length-1)*FONT_SIZE/2;
}*/
drawCenteredText(cs, font, FONT_SIZE, title,
startX + LEFT_COL_WIDTH/2, textY);
// 绘制图片带5pt边距
cs.drawImage(image,
startX + LEFT_COL_WIDTH + 5,
startY - rowHeight + 10,
imageWidth, imageHeight);
return startY - rowHeight - 10;
/*// 计算图片尺寸(保持比例)
float imageWidth = RIGHT_COL_WIDTH - 10;
float scale = imageWidth / image.getWidth();
float imageHeight = image.getHeight() * scale;
// 动态计算行高(图片高度+上下边距20
float dynamicRowHeight = imageHeight + 20;
// 绘制左侧标题单元格
cs.setLineWidth(0.5f);
cs.addRect(TABLE_MARGIN, startY - dynamicRowHeight, LEFT_COL_WIDTH, dynamicRowHeight);
// 绘制右侧图片单元格(高度与左侧同步)
cs.addRect(TABLE_MARGIN + LEFT_COL_WIDTH, startY - dynamicRowHeight, RIGHT_COL_WIDTH, dynamicRowHeight);
cs.stroke();
// 居中绘制标题文本
float titleWidth = font.getStringWidth(title) / 1000 * FONT_SIZE;
float titleX = TABLE_MARGIN + (LEFT_COL_WIDTH - titleWidth) / 2;
float titleY = startY - (dynamicRowHeight / 2) - (FONT_SIZE / 3);
cs.beginText();
cs.setFont(font, FONT_SIZE);
cs.newLineAtOffset(titleX, titleY);
cs.showText(title);
cs.endText();
// 居中绘制图片
float imageX = TABLE_MARGIN + LEFT_COL_WIDTH + 5;
float imageY = startY - dynamicRowHeight + 10;
cs.drawImage(image, imageX, imageY, imageWidth, imageHeight);
// 返回新的Y坐标当前位置减去行高和间距
return startY - dynamicRowHeight - 10;*/
}
/* private static float addImageRow(PDPageContentStream cs, PDDocument doc,
PDType0Font font, String title, String imageUrl, float x, float y) throws IOException {
// 绘制标题行
// 加载并绘制图片(居中)
PDImageXObject image = PDImageXObject.createFromByteArray(doc,
new URL(imageUrl).openStream().readAllBytes(), "embedded-image");
// 计算图片尺寸(保持比例)
// 加载并绘制图片
// 计算图片缩放比例
float imageWidth = RIGHT_COL_WIDTH - 10;
float scale = imageWidth / image.getWidth();
float imageHeight = image.getHeight() * scale;
float rowHeight = Math.max(ROW_HEIGHT, imageHeight + 10);
// 绘制图片行边框
cs.setLineWidth(0.5f);
cs.addRect(TABLE_MARGIN, y - rowHeight, LEFT_COL_WIDTH, rowHeight);
cs.addRect(TABLE_MARGIN + LEFT_COL_WIDTH, y - rowHeight, RIGHT_COL_WIDTH, rowHeight);
cs.stroke();
String[][] titleData = {{title, ""}};
// drawTable(cs, font, x, y, titleData, new float[]{COLUMN_LEFT_WIDTH, COLUMN_WIDTH});
// 写入标题文本
// 新代码(居中显示)
float titleWidth = font.getStringWidth(title) / 1000 * 20; // 计算文本宽度
float centerX = TABLE_MARGIN + (LEFT_COL_WIDTH - titleWidth) / 2; // 计算居中位置
cs.beginText();
cs.setFont(font, 20);
cs.newLineAtOffset(centerX, y - 15); // 使用计算出的居中位置
cs.showText(title);
cs.endText();
// 绘制图片(居中显示)
float imageY = y - (rowHeight/2) - (imageHeight/2);
cs.drawImage(image, TABLE_MARGIN + LEFT_COL_WIDTH + 5, imageY, imageWidth, imageHeight);
y -= rowHeight + 10;
return y - rowHeight - 10; // 返回新的Y坐标
}*/
private static void drawCenteredText(PDPageContentStream cs, PDType0Font font,
float fontSize, String text, float centerX, float baselineY) throws IOException {
float textWidth = font.getStringWidth(text) / 1000 * fontSize;
cs.setFont(font, fontSize);
cs.beginText();
// 原始调用改进为
cs.newLineAtOffset(centerX - textWidth / 2, baselineY);
cs.showText(text);
cs.endText();
}
}

@ -26,6 +26,8 @@ import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.common.api.Request;
import cc.iotkit.common.api.Response;
import cc.iotkit.common.excel.convert.ExcelBigNumberConvert;
import cc.iotkit.common.excel.core.CellMergeStrategy;
import cc.iotkit.common.excel.utils.ExcelUtil;
import cc.iotkit.common.log.annotation.Log;
import cc.iotkit.common.log.enums.BusinessType;
@ -58,9 +60,11 @@ import cc.iotkit.model.device.message.DeviceProperty;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.ExcelWriter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.sl.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -125,7 +129,7 @@ public class DeviceController {
@ApiOperation(value = "创建设备")
@SaCheckPermission("iot:device:add")
@PostMapping("/add")
public boolean createDevice(@RequestBody @Validated Request<DeviceInfoBo> bo) {
public boolean createDevice(@RequestBody @Validated Request<DeviceInfoAddBo> bo) {
return deviceServiceImpl.addDevice(bo.getData());
}
@ -204,20 +208,21 @@ public class DeviceController {
@Log(title = "设备管理", businessType = BusinessType.EXPORT)
// @SaCheckPermission("system:user:export")@RequestBody Request<ProductBo>
@PostMapping("/export")
public void export(DeviceQueryBo deviceQueryBo,
public void export(@Validated @RequestBody PageRequest<DeviceQueryBo> deviceQueryBo,
HttpServletResponse response) {
if(ObjectUtil.isEmpty(deviceQueryBo)){
if(LoginHelper.isSuperAdmin() && TenantHelper.getTenantId() == 0){
deviceQueryBo.setTenantId(null);
deviceQueryBo.getData().setTenantId(null);
}else{
deviceQueryBo.setTenantId(TenantHelper.getTenantId());
deviceQueryBo.getData().setTenantId(TenantHelper.getTenantId());
}
}
List<DeviceInfoVo> list = deviceServiceImpl.getDevicess(deviceQueryBo);
List<DeviceInfoVo> list = deviceServiceImpl.getDevicessExcel(deviceQueryBo);
List<DeviceInfoExpordVo> listVo = MapstructUtils.convert(list, DeviceInfoExpordVo.class);
ExcelUtil.exportExcel(listVo, "设备数据", DeviceInfoExpordVo.class, response);
}
@ApiOperation("设备物模型日志")
@SaCheckPermission("iot:deviceLog:query")
@PostMapping("/deviceLogs/list")

@ -27,14 +27,23 @@ import cc.iotkit.common.api.Paging;
import cc.iotkit.common.api.Request;
import cc.iotkit.common.constant.Constants;
import cc.iotkit.common.enums.ErrCode;
import cc.iotkit.common.excel.utils.ExcelUtil;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.log.annotation.Log;
import cc.iotkit.common.log.enums.BusinessType;
import cc.iotkit.common.satoken.utils.LoginHelper;
import cc.iotkit.common.tenant.helper.TenantHelper;
import cc.iotkit.common.utils.MapstructUtils;
import cc.iotkit.data.manager.IDeviceInstallInfoData;
import cc.iotkit.manager.config.GasInstallationPDFGenerator;
import cc.iotkit.manager.config.PDFGenerator;
import cc.iotkit.manager.dto.bo.device.DeviceDetectorQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceInstallInfoQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceQueryBo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInfoExpordVo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInfoVo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInstallInfoExpordVo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInstallInfoVo;
import cc.iotkit.manager.service.IDeviceDetectorInfoService;
import cc.iotkit.manager.service.IDeviceInstallInfoService;
import cc.iotkit.model.UserInfo;
@ -192,6 +201,26 @@ public class DeviceInstallInfoController {
PDFGenerator.generateInstallationPDF(data, response.getOutputStream());
}
@ApiOperation("导出设备列表")
@Log(title = "导出设备列表", businessType = BusinessType.EXPORT)
// @SaCheckPermission("system:user:export")@RequestBody Request<ProductBo>
@PostMapping("/export")
public void export(@Validated @RequestBody PageRequest<DeviceInstallInfoQueryBo> pageRequest,
HttpServletResponse response) {
if(ObjectUtil.isEmpty(pageRequest.getData())){
if(LoginHelper.isSuperAdmin() && TenantHelper.getTenantId() == 0){
pageRequest.getData().setTenantId(null);
}else{
pageRequest.getData().setTenantId(TenantHelper.getTenantId());
}
}
List<DeviceInstallInfoVo> list = deviceServiceImpl.getList(pageRequest);
// List<DeviceInfoVo> list = deviceServiceImpl.getDevicess(deviceQueryBo);
List<DeviceInstallInfoExpordVo> listVo = MapstructUtils.convert(list, DeviceInstallInfoExpordVo.class);
ExcelUtil.exportExcel(listVo, "每日安装明细", DeviceInstallInfoExpordVo.class, response);
}
// @PostMapping("/getPdf")
@SaCheckPermission("device:install:upload")
public void getPdf1(@Validated @RequestBody Request<String> request, HttpServletResponse response) throws Exception {

@ -0,0 +1,129 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.manager.dto.bo.device;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.DeviceInstallInfo;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Size;
import java.util.HashMap;
import java.util.Map;
@ApiModel(value = "DeviceInfoAddBo")
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = DeviceInfo.class, reverseConvertGenerate = false)
public class DeviceInfoAddBo extends BaseDto {
private static final long serialVersionUID = -1L;
private String id;
@ApiModelProperty(value = "创建时间")
private Long createAt;
@ApiModelProperty(value = "设备id")
@Size(max = 255, message = "设备id长度不正确")
private String deviceId;
@ApiModelProperty(value = "设备名称")
@Size(max = 255, message = "设备名称长度不正确")
private String deviceName;
@ApiModelProperty(value = "设备类型")
@Size(max = 255, message = "设备类型长度不正确")
private String model;
@ApiModelProperty(value = "设备离线时间")
private Long offlineTime;
@ApiModelProperty(value = "设备在线时间")
private Long onlineTime;
@ApiModelProperty(value = "父级id")
@Size(max = 255, message = "父级id长度不正确")
private String parentId;
@ApiModelProperty(value = "产品key")
@Size(max = 255, message = "产品key长度不正确")
// @NotBlank(message = "产品Key不能为空")
private String productKey;
@ApiModelProperty(value = "设备描述")
@Size(max = 255, message = "设备描述长度不正确")
private String secret;
@ApiModelProperty(value = "经度")
private String longitude;
@ApiModelProperty(value = "纬度")
private String latitude;
@ApiModelProperty(value = "详细地址")
private String site;
private String name;
@ApiModelProperty(value="部门表-区域id")
private Long deptAreaId;
@ApiModelProperty(value = "用户id")
@Size(max = 255, message = "用户id长度不正确")
private String uid;
private Long tenantId;
private String groupId;
private DeviceInstallInfo deviceInstallInfo;
private String nodeOne;
private String nodeTwo;
private String nodeThree;
private String nodeFour;
private String nodeFive;
private String nodeOneStatus;
private String nodeTwoStatus;
private String nodeThreeStatus;
private String nodeFourStatus;
private String nodeFiveStatus;
private String nodeOneDevice;
private String nodeTwoDevice;
private String nodeThreeDevice;
private String nodeFourDevice;
private String nodeFiveDevice;
/**
*
*/
/* private Map<String, DeviceInfo.Group> group = new HashMap<>();
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Group {
private String id;
private String name;
}*/
}

@ -26,11 +26,17 @@ package cc.iotkit.manager.dto.bo.device;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.DeviceInstallInfo;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.annotations.ReverseAutoMapping;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Data;
@ -116,4 +122,37 @@ public class DeviceInfoBo extends BaseDto {
private String nodeThreeDevice;
private String nodeFourDevice;
private String nodeFiveDevice;
/**
*
*/
private Map<String, DeviceInfo.Group> group = new HashMap<>();
// private static final ObjectMapper mapper = new ObjectMapper();
// 使用 @JsonAnySetter 处理动态键
//@JsonSetter
/* public void setGroup(Object value) {
if (value instanceof Map) {
this.group = (Map<String, DeviceInfo.Group>) value;
}
// 否则不进行赋值保持原来的空Map
}*/
public void setGroup(Object value) {
if (value instanceof Map) {
ObjectMapper mapper = new ObjectMapper();
this.group = mapper.convertValue(
value,
new TypeReference<Map<String, DeviceInfo.Group>>(){}
);
}
}
// private Object group;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Group {
private String id;
private String name;
}
}

@ -102,4 +102,6 @@ public class DeviceInstallInfoQueryBo extends BaseDto {
private String userName;
// @ApiModelProperty(value = "用户电话")
private String userIpone;
//绑定人电话
private String bindUserIpone;
}

@ -83,4 +83,8 @@ public class DeviceQueryBo extends BaseDto {
@ApiModelProperty(value="设备名称")
private String name;
private Boolean flag = false;
@ApiModelProperty(value = "设备名称")
private String startTime;
@ApiModelProperty(value = "设备名称")
private String endTime;
}

@ -132,4 +132,6 @@ public class DeviceInfoVo implements Serializable {
private String nodeThreeDevice;
private String nodeFourDevice;
private String nodeFiveDevice;
private String longitude;
private String latitude;
}

@ -0,0 +1,82 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.manager.dto.vo.deviceinfo;
import cc.iotkit.model.device.DeviceInstallInfo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = DeviceInstallInfoVo.class, convertGenerate = false)
public class DeviceInstallInfoExpordVo implements Serializable {
private static final long serialVersionUID = 1L;
/* // @ApiModelProperty(value = "申请人")
private String proposer;
// @ApiModelProperty(value = "申请班组")
private String proposerTeam;
// @ApiModelProperty(value = "小区名称")
private String communityName;*/
// @ApiModelProperty(value = "用户名称")
@ExcelProperty(value = "序号")
private Integer xuhao;
@ExcelProperty(value = "姓名")
private String userName;
// @ApiModelProperty(value = "用户电话")
@ExcelProperty(value = "电话")
private String userIpone;
// @ApiModelProperty(value = "切断阀编号")
@ExcelProperty(value = "地址")
private String site;
// @ApiModelProperty(value = "燃气表号")
@ExcelProperty(value = "表号")
private String gasMeterNumber;
@ExcelProperty(value = "安装人")
private String proposer;
@ExcelProperty(value = "安装时间")
// @ApiModelProperty(value = "申请时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date proposerTime;
@ExcelProperty(value = "厂家")
private String manufacturer;
@ExcelProperty(value = "安装情况")
private String position;
/* // @ApiModelProperty(value = "备注")
private String remarks;
private Integer state;*/
}

@ -0,0 +1,85 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.manager.dto.vo.deviceinfo;
import cc.iotkit.model.Owned;
import cc.iotkit.model.TenantModel;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.DeviceInstallInfo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModel;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@ApiModel(value = "DeviceInstallInfoVo")
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = DeviceInstallInfo.class, convertGenerate = false)
public class DeviceInstallInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
/* // @ApiModelProperty(value = "申请人")
private String proposer;
// @ApiModelProperty(value = "申请班组")
private String proposerTeam;
// @ApiModelProperty(value = "小区名称")
private String communityName;*/
// @ApiModelProperty(value = "用户名称")
@ExcelProperty(value = "序号")
private Integer xuhao;
@ExcelProperty(value = "姓名")
private String userName;
// @ApiModelProperty(value = "用户电话")
@ExcelProperty(value = "电话")
private String userIpone;
// @ApiModelProperty(value = "切断阀编号")
@ExcelProperty(value = "地址")
private String site;
// @ApiModelProperty(value = "燃气表号")
@ExcelProperty(value = "表号")
private String gasMeterNumber;
@ExcelProperty(value = "安装人")
private String proposer;
@ExcelProperty(value = "安装时间")
// @ApiModelProperty(value = "申请时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date proposerTime;
@ExcelProperty(value = "厂家")
private String manufacturer;
@ExcelProperty(value = "安装情况")
private String position;
/* // @ApiModelProperty(value = "备注")
private String remarks;
private Integer state;*/
}

@ -29,6 +29,7 @@ import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.satoken.utils.LoginHelper;
import cc.iotkit.common.utils.SpringUtils;
import cc.iotkit.common.utils.StringUtils;
import cc.iotkit.manager.dto.bo.device.DeviceInfoAddBo;
import cc.iotkit.manager.dto.bo.device.DeviceInfoBo;
import cc.iotkit.manager.dto.bo.devicegroup.DeviceAddGroupBo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInfoImportVo;
@ -104,7 +105,7 @@ public class DeviceInfoImportListener extends AnalysisEventListener<DeviceInfoIm
// todo 处理groups
if(ObjectUtil.isNull(deviceInfo)) {
// 新增
DeviceInfoBo deviceInfoBo = BeanUtil.toBean(deviceInfoImportVo, DeviceInfoBo.class);
DeviceInfoAddBo deviceInfoBo = BeanUtil.toBean(deviceInfoImportVo, DeviceInfoAddBo.class);
this.deviceManagerService.addDevice(deviceInfoBo);
// 新增后重新获取deviceInfo 此操作冗余,是建立在不修改源码基础上的处理方式,可优化
deviceInfo = this.deviceManagerService.getByPkDn(deviceInfoImportVo.getProductKey(), deviceInfoImportVo.getDeviceName());

@ -29,6 +29,7 @@ import cc.iotkit.data.manager.IAlertConfigData;
import cc.iotkit.data.manager.IAlertRecordData;
import cc.iotkit.model.alert.AlertConfig;
import cc.iotkit.model.alert.AlertRecord;
import cc.iotkit.model.alert.AlertRecordBo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -79,16 +80,19 @@ public class AlertService {
.build());
}
public void addAlert(AlertConfig config, String content,Long tenandId, String uid,Long deptAreaId) {
alertRecordData.save(AlertRecord.builder()
.level(config.getLevel())
.name(config.getName())
.tenantId(tenandId)
.uid(uid)
.deptAreaId(deptAreaId)
.readFlg(false)
.alertTime(System.currentTimeMillis())
.details(content)
.build());
// List<AlertRecord> alerts = alertRecordData.selectAlertConfigPage(AlertRecordBo.builder().details(content).build());
// if(alerts.isEmpty()) {
alertRecordData.save(AlertRecord.builder()
.level(config.getLevel())
.name(config.getName())
.tenantId(tenandId)
.uid(uid)
.deptAreaId(deptAreaId)
.readFlg(false)
.alertTime(System.currentTimeMillis())
.details(content)
.build());
// }
}
}

@ -134,6 +134,9 @@ public class DeviceCtrlService {
DeviceInfo device = getAndCheckDevice(deviceId, checkOwner);
DeviceConfig config = deviceConfigData.findByDeviceId(deviceId);
if (config == null || ObjectUtil.isEmpty(config)) {
fail("设备未配置");
}
Map data = JsonUtils.parseObject(config.getConfig(), Map.class);
return send(deviceId, device.getProductKey(), device.getDeviceName(), data,

@ -65,7 +65,7 @@ public class DeviceStateCheckTask {
Paging<DeviceInfo> all;
while (true) {
//取出数据库中所有在线设备
all = deviceInfoData.findByConditions("","","","","",true,"",pn,1000,null);
all = deviceInfoData.findByConditions("","","","","",true,"",pn,1000,null,null,null);
//判断属性更新时间是否大于产品定义保活时长
for (DeviceInfo device : all.getRows()) {
if(ObjectUtil.isNull(device)){

@ -27,6 +27,7 @@ import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.manager.dto.bo.device.DeviceDetectorQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceInstallInfoQueryBo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInstallInfoVo;
import cc.iotkit.model.device.DeviceDetectorInfo;
import cc.iotkit.model.device.DeviceInstallInfo;
@ -40,5 +41,5 @@ import java.util.List;
*/
public interface IDeviceInstallInfoService {
Paging<DeviceInstallInfo> getPage(PageRequest<DeviceInstallInfoQueryBo> pageRequest);
// List<DeviceInstallInfo> getList(PageRequest<DeviceInstallInfoQueryBo> pageRequest);
List<DeviceInstallInfoVo> getList(PageRequest<DeviceInstallInfoQueryBo> pageRequest);
}

@ -26,10 +26,7 @@ package cc.iotkit.manager.service;
import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.common.thing.ThingModelMessage;
import cc.iotkit.manager.dto.bo.device.DeviceInfoBo;
import cc.iotkit.manager.dto.bo.device.DeviceLogQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceTagAddBo;
import cc.iotkit.manager.dto.bo.device.*;
import cc.iotkit.manager.dto.bo.devicegroup.DeviceAddGroupBo;
import cc.iotkit.manager.dto.bo.devicegroup.DeviceGroupBo;
import cc.iotkit.manager.dto.vo.deviceconfig.DeviceConfigVo;
@ -56,7 +53,10 @@ public interface IDeviceManagerService {
Paging<DeviceInfoVo> getDevices1(PageRequest<DeviceQueryBo> pageRequest);
public List<DeviceInfoVo> findByConditionsList(String productKey,boolean flag);
List<DeviceInfoVo> getDevicess(DeviceQueryBo pageRequest);
boolean addDevice(DeviceInfoBo data);
List<DeviceInfoVo> getDevicessExcel(PageRequest<DeviceQueryBo> pageRequest);
boolean addDevice(DeviceInfoAddBo data);
List<DeviceInfoVo> selectChildrenPageList(String deviceId);

@ -10,13 +10,16 @@ import cc.iotkit.data.dao.DeviceIDetectornfoRepository;
import cc.iotkit.data.dao.DeviceInstallInfoRepository;
import cc.iotkit.data.manager.IDeviceDetectorInfoData;
import cc.iotkit.data.manager.IDeviceInstallInfoData;
import cc.iotkit.data.manager.IUserInfoData;
import cc.iotkit.data.model.TbDeviceDetectorInfo;
import cc.iotkit.data.model.TbDeviceInstallInfo;
import cc.iotkit.data.util.PredicateBuilder;
import cc.iotkit.manager.dto.bo.device.DeviceDetectorQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceInstallInfoQueryBo;
import cc.iotkit.manager.dto.vo.deviceinfo.DeviceInstallInfoVo;
import cc.iotkit.manager.service.IDeviceDetectorInfoService;
import cc.iotkit.manager.service.IDeviceInstallInfoService;
import cc.iotkit.model.UserInfo;
import cc.iotkit.model.device.DeviceDetectorInfo;
import cc.iotkit.model.device.DeviceInstallInfo;
import cn.hutool.core.util.ObjectUtil;
@ -54,6 +57,8 @@ public class DeviceInstallInfoServiceImpl implements IDeviceInstallInfoService {
@Autowired
private IDeviceInstallInfoData iDeviceInstallInfoData;
@Autowired
private IUserInfoData iUserInfoData;
@Autowired
private DeviceInstallInfoRepository deviceInstallInfoRepository;
private final JPAQueryFactory jpaQueryFactory;
@ -84,6 +89,15 @@ public class DeviceInstallInfoServiceImpl implements IDeviceInstallInfoService {
}
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getBindUserIpone())){
List<UserInfo> userInfoList = iUserInfoData.findByUserNameLike(pageReqVO.getData().getBindUserIpone());
String[] uidArray = userInfoList.stream()
.map(UserInfo::getUid)
.toArray(String[]::new);
if(ObjectUtil.isNotEmpty(uidArray)) {
query.where(tbDeviceInstallInfo.uid.in(uidArray));
}
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getDeviceName())) {
query.where(tbDeviceInstallInfo.deviceName.like("%" + pageReqVO.getData().getDeviceName() +"%"));
}
@ -125,6 +139,12 @@ public class DeviceInstallInfoServiceImpl implements IDeviceInstallInfoService {
for (TbDeviceInstallInfo tbDeviceInfo : tbDeviceInfos) {
DeviceInstallInfo deviceInfo = MapstructUtils.convert(tbDeviceInfo, DeviceInstallInfo.class);
//fillDeviceInfo(tbDeviceInfo.getDeviceId(), tbDeviceInfo, deviceInfo);
if(ObjectUtil.isNotEmpty(tbDeviceInfo.getUid())) {
UserInfo userInfo = iUserInfoData.findByUid(tbDeviceInfo.getUid());
if(ObjectUtil.isNotEmpty(userInfo)) {
deviceInfo.setBindUserIpone(userInfo.getUserName());
}
}
deviceInfos.add(deviceInfo);
}
return new Paging<>(total, deviceInfos);
@ -135,7 +155,89 @@ public class DeviceInstallInfoServiceImpl implements IDeviceInstallInfoService {
}
// 构建动态查询条件(含排序)
@Override
public List<DeviceInstallInfoVo> getList(PageRequest<DeviceInstallInfoQueryBo> pageReqVO) {
//return idIccidRecordData.findAll(pageReqVO.to(DIccidRecordDO.class)).to(DIccidRecordRespVO.class);
// 构建分页时指定排序规则
/* Pageable pageable = PageRequest.of(
pageReqVO..getPage(),
pageReqVO.getSize(),
Sort.by(Sort.Direction.DESC, "createTime") // 按创建时间降序
);*/
JPAQuery<TbDeviceInstallInfo> query = jpaQueryFactory.selectFrom(tbDeviceInstallInfo);
if (ObjectUtil.isNotNull(pageReqVO.getData().getStartTime())&& ObjectUtil.isNotNull(pageReqVO.getData().getEndTime())) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDateTime = sdf.parse(pageReqVO.getData().getStartTime());
Date dateTime = sdf.parse(pageReqVO.getData().getEndTime());
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime startDateTime = LocalDateTime.parse(dictData.getStartTime() , formatter);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// LocalDateTime dateTime = LocalDateTime.parse(dictData.getEndTime(), formatter);
query.where(tbDeviceInstallInfo.proposerTime.between(startDateTime, dateTime));
} catch (Exception e) {
}
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getDeviceName())) {
query.where(tbDeviceInstallInfo.deviceName.like("%" + pageReqVO.getData().getDeviceName() +"%"));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getUid())) {
query.where(tbDeviceInstallInfo.uid.eq(pageReqVO.getData().getUid()));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getCorporateName())) {
query.where(tbDeviceInstallInfo.corporateName.like("%" + pageReqVO.getData().getCorporateName() +"%"));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getProposer())) {
query.where(tbDeviceInstallInfo.proposer.like("%" + pageReqVO.getData().getProposer() +"%"));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getProposerTeam())) {
query.where(tbDeviceInstallInfo.proposerTeam.like("%" + pageReqVO.getData().getProposerTeam() +"%"));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getCommunityName())) {
query.where(tbDeviceInstallInfo.communityName.like("%" + pageReqVO.getData().getCommunityName() +"%"));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getUserName())) {
query.where(tbDeviceInstallInfo.userName.like("%" + pageReqVO.getData().getUserName() +"%"));
}
if(ObjectUtil.isNotNull(pageReqVO.getData().getUserIpone())) {
query.where(tbDeviceInstallInfo.userIpone.like("%" + pageReqVO.getData().getUserIpone() +"%"));
}
if(LoginHelper.isSuperAdmin() && TenantHelper.getTenantId() != 0){
query.where(tbDeviceInstallInfo.tenantId.eq(TenantHelper.getTenantId()));
}
if(!LoginHelper.isSuperAdmin() && ObjectUtil.isNotNull(pageReqVO.getData().getTenantId())){
query.where(tbDeviceInstallInfo.tenantId.eq(pageReqVO.getData().getTenantId()));
}
query.orderBy(tbDeviceInstallInfo.createTime.desc());
// Integer page = ObjectUtil.isNotNull(pageReqVO.getPageNum()) ?pageReqVO.getPageNum():1;
//Integer size = ObjectUtil.isNotNull(pageReqVO.getPageSize()) ?pageReqVO.getPageSize():10;
//query.offset((page - 1) * size).limit(size);
List<TbDeviceInstallInfo> tbDeviceInfos = query.fetch();
List<DeviceInstallInfoVo> deviceInfos = new ArrayList<>(tbDeviceInfos.size());
// long total = query.fetchCount();
int i = 1;
for (TbDeviceInstallInfo tbDeviceInfo : tbDeviceInfos) {
DeviceInstallInfo deviceInfo = MapstructUtils.convert(tbDeviceInfo, DeviceInstallInfo.class);
DeviceInstallInfoVo deviceInstallInfoVo = MapstructUtils.convert(deviceInfo, DeviceInstallInfoVo.class);
deviceInstallInfoVo.setXuhao(i);
deviceInstallInfoVo.setSite(tbDeviceInfo.getCommunityName() + tbDeviceInfo.getBuildingUnit() + tbDeviceInfo.getRoomNo());
deviceInstallInfoVo.setManufacturer("天津费加罗");
deviceInstallInfoVo.setPosition("成功");
//fillDeviceInfo(tbDeviceInfo.getDeviceId(), tbDeviceInfo, deviceInfo);
deviceInfos.add(deviceInstallInfoVo);
i++;
}
return deviceInfos;
/* return PageBuilder.toPaging(deviceIDetectornfoRepository.findAll(
buildQueryCondition(pageReqVO.getData()),
PageBuilder.toPageable(pageReqVO)
)).to(DeviceDetectorInfo.class);*/
}
/* @Override
public List<DeviceDetectorInfo> getList(PageRequest<DeviceDetectorQueryBo> pageReqVO) {
//return idIccidRecordData.findAll(pageReqVO.to(DIccidRecordDO.class)).to(DIccidRecordRespVO.class);

@ -40,10 +40,7 @@ import cc.iotkit.data.dao.DeviceInfoRepository;
import cc.iotkit.data.manager.*;
import cc.iotkit.data.model.TbDeviceInfo;
import cc.iotkit.data.system.ISysDeptData;
import cc.iotkit.manager.dto.bo.device.DeviceInfoBo;
import cc.iotkit.manager.dto.bo.device.DeviceLogQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceQueryBo;
import cc.iotkit.manager.dto.bo.device.DeviceTagAddBo;
import cc.iotkit.manager.dto.bo.device.*;
import cc.iotkit.manager.dto.bo.devicegroup.DeviceAddGroupBo;
import cc.iotkit.manager.dto.bo.devicegroup.DeviceGroupBo;
import cc.iotkit.manager.dto.vo.deviceconfig.DeviceConfigVo;
@ -79,13 +76,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
import static cc.iotkit.common.web.core.BaseController.fail;
@ -151,7 +147,7 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
Boolean online = query.getOnline();
Long areaDepeId = query.getDeptAreaId();
Paging<DeviceInfoVo> result = MapstructUtils.convert(deviceInfoData.findByConditions(name, uid, subUid, pk, group,
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId), DeviceInfoVo.class);
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId,query.getStartTime(), query.getEndTime()), DeviceInfoVo.class);
for (DeviceInfoVo row : result.getRows()) {
row.setProduct(productData.findByProductKey(row.getProductKey()));
}
@ -171,7 +167,7 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
Boolean online = query.getOnline();
Long areaDepeId = query.getDeptAreaId();
Paging<DeviceInfoVo> result = MapstructUtils.convert(deviceInfoData.findByConditions1(name, uid, subUid, pk, group,
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId), DeviceInfoVo.class);
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId,query.getStartTime(), query.getEndTime()), DeviceInfoVo.class);
for (DeviceInfoVo row : result.getRows()) {
row.setProduct(productData.findByProductKey(row.getProductKey()));
}
@ -189,6 +185,30 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
return selectedDevices;
}
public List<DeviceInfoVo> getDevicessExcel(PageRequest<DeviceQueryBo> pageRequest) {
/* DeviceInfo deviceInfo = pageRequest.to(DeviceInfo.class);
deviceInfo.setState(null);
List<DeviceInfoVo> selectedDevices = MapstructUtils.convert(deviceInfoData.findAllByCondition(deviceInfo), DeviceInfoVo.class);
*/
DeviceQueryBo query = pageRequest.getData();
String uid = query.getUid();
String subUid = "";
String name = query.getName();
String pk = query.getProductKey();
//关键字查询
String keyword = query.getKeyword();
String group = query.getGroup();
Boolean online = query.getOnline();
Long areaDepeId = query.getDeptAreaId();
//pageRequest.setPageSize(99999);
Paging<DeviceInfoVo> result = MapstructUtils.convert(deviceInfoData.findByConditionsExcel(name, uid, subUid, pk, group,
online, keyword, pageRequest.getPageNum(), pageRequest.getPageSize(), areaDepeId,query.getStartTime(), query.getEndTime()), DeviceInfoVo.class);
/* for (DeviceInfoVo row : result.getRows()) {
row.setProduct(productData.findByProductKey(row.getProductKey()));
}*/
return result.getRows();
}
@Override
public List<DeviceInfoVo> findByConditionsList(String productKey, boolean flag) {
return MapstructUtils.convert(iDeviceInfoData.findByConditionsList(productKey, flag), DeviceInfoVo.class);
@ -196,7 +216,7 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
}
@Override
public boolean addDevice(DeviceInfoBo deviceInfo) {
public boolean addDevice(DeviceInfoAddBo deviceInfo) {
String productKey = deviceInfo.getProductKey();
String deviceName = deviceInfo.getDeviceName();
@ -227,11 +247,11 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
/* if(ObjectUtil.isNotNull(sysDept) && ObjectUtil.isNull(deviceInfo.getTenantId())) {
device.setTenantId(sysDept.getTenantId());
}*/
if (ObjectUtil.isNotNull(sysDept)) {
if (ObjectUtil.isNotNull(sysDept) && ObjectUtil.isNull(deviceInfo.getTenantId()) ) {
device.setTenantId(sysDept.getTenantId());
}
if (LoginHelper.isSuperAdmin() && TenantHelper.getTenantId() == 0) {
if (ObjectUtil.isNotNull(sysDept)) {
if (ObjectUtil.isNotNull(sysDept) && ObjectUtil.isNull(deviceInfo.getTenantId())) {
device.setTenantId(sysDept.getTenantId());
}
}
@ -550,10 +570,12 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
@Override
public boolean saveDevice(DeviceInfoBo data) {
DeviceInfo di = data.to(DeviceInfo.class);
if (ObjectUtil.isNotNull(data.getGroupId()) && !data.getGroupId().equals("{}")) {
if (ObjectUtil.isEmpty(di.getGroup()) && ObjectUtil.isNotNull(data.getGroupId()) && !data.getGroupId().equals("{}")) {
di.getGroup().put(data.getGroupId(), new DeviceInfo.Group(
data.getGroupId(), data.getDeviceId()));
}
}/*else if(process(data)){
di.setGroup(convert(data.getGroup()));
}*/
di.setLocate(new DeviceInfo.Locate(data.getLongitude(), data.getLatitude()));
if (StringUtils.isBlank(data.getSecret())) {
data.setSecret(RandomStringUtils.random(16));
@ -581,7 +603,7 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
if (deviceRepetition != null && !deviceRepetition.getDeviceId().equals(di.getDeviceId())) {
throw new BizException(ErrCode.MODEL_DEVICE_ALREADY);
}
if(ObjectUtil.isNotNull(deviceRepetition.getState())) {
if(ObjectUtil.isNotEmpty(deviceRepetition) && ObjectUtil.isNotNull(deviceRepetition.getState())) {
di.setState(deviceRepetition.getState());
}
/* if(ObjectUtil.isNotNull(data.getGroup())){
@ -591,6 +613,36 @@ public class DeviceManagerServiceImpl implements IDeviceManagerService {
TenantHelper.enableIgnore();
return deviceInfoData.save(di) != null;
}
public static Map<String, DeviceInfo.Group> convert(Object obj) {
return obj instanceof Map ? ((Map<?,?>) obj).entrySet().stream()
.filter(e -> e.getKey() instanceof String)
.filter(e -> e.getValue() instanceof DeviceInfo.Group)
.collect(Collectors.toMap(
e -> (String)e.getKey(),
e -> (DeviceInfo.Group)e.getValue()
)) : Collections.emptyMap();
}
public boolean process(DeviceInfoBo dto) {
Object input = dto.getGroup();
if(input == null){
return false;
}
if (input instanceof Map) {
// 处理Map逻辑
return true;
}else if(isMapFormat(input.toString())){
// 处理Map逻辑
return true;
} else {
// 处理其他类型或默认值
return false;
}
}
public boolean isMapFormat(String input) {
return input.matches("^\\{(\\w+:\\w+,?)*\\}$");
}
@Override
public boolean saveDevice1(DeviceInfoBo data) {

@ -17,7 +17,10 @@
<groupId>cc.iotkit</groupId>
<artifactId>iot-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-rule-engine</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common-redis</artifactId>

@ -35,6 +35,9 @@ import cc.iotkit.common.utils.JsonUtils;
import cc.iotkit.common.utils.StringUtils;
import cc.iotkit.common.utils.UniqueIdUtil;
import cc.iotkit.data.manager.*;
import cc.iotkit.model.alert.AlertConfig;
import cc.iotkit.model.alert.AlertRecord;
import cc.iotkit.model.alert.AlertRecordBo;
import cc.iotkit.model.device.DeviceDetectorInfo;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.iccid.DIccidRecordDO;
@ -46,6 +49,9 @@ import cc.iotkit.plugin.core.thing.actions.down.DeviceConfig;
import cc.iotkit.plugin.core.thing.actions.up.*;
import cc.iotkit.plugin.core.thing.model.ThingDevice;
import cc.iotkit.plugin.core.thing.model.ThingProduct;
import cc.iotkit.ruleengine.rule.Rule;
import cc.iotkit.ruleengine.rule.RuleExecutor;
import cc.iotkit.ruleengine.rule.RuleMessageHandler;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
@ -60,9 +66,12 @@ import javax.annotation.security.PermitAll;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static cc.iotkit.common.redis.utils.RedisUtils.setCacheMapValue;
import static cc.iotkit.common.redis.utils.RedisUtils.*;
import static com.ibm.icu.impl.Assert.fail;
/**
@ -92,29 +101,46 @@ public class ThingServiceImpl implements IThingService {
private IDIccidRecordData idIccidRecordData;
@Autowired
private IDeviceDetectorInfoData iDeviceDetectorInfoData;
@Autowired
private IAlertRecordData idAlertRecordData;
@Autowired
private IAlertConfigData iAlertConfigData;
@Autowired
private RuleExecutor ruleExecutor;
@Autowired
private RuleMessageHandler ruleMessageHandler;
@Override
public ActionResult post(String pluginId, IDeviceAction action) {
try {
log.info("receive plugin:{}, action:{}", pluginId, action);
String deviceName = action.getDeviceName();
if (!"NONE".equals(pluginId)) {
//添加设备路由
deviceRouter.putRouter(deviceName, new PluginRouter(IPluginMain.MAIN_ID, pluginId));
}
long lastTime = System.currentTimeMillis();
DeviceInfo device = getDeviceInfo(deviceName);
// DeviceStateChange deviceInfo = ((DeviceStateChange) action);
/* if(ObjectUtil.isNotNull(deviceInfo.getState())){
if (deviceInfo.getState().equals(DeviceState.ONLINE)) {
device.getState().setOnline(true);
device.getState().setOnlineTime(System.currentTimeMillis());
} else {
device.getState().setOnline(false);
device.getState().setOfflineTime(System.currentTimeMillis());
if (ObjectUtil.isNotEmpty(action)) {
try {
DeviceStateChange deviceInfo = ((DeviceStateChange) action);
if (ObjectUtil.isNotEmpty(deviceInfo) && ObjectUtil.isNotNull(deviceInfo.getState())) {
// if (deviceInfo.getState().equals(DeviceState.ONLINE)) {
device.getState().setOnline(true);
device.getState().setOnlineTime(System.currentTimeMillis());
/* } else {
device.getState().setOnline(false);
device.getState().setOfflineTime(System.currentTimeMillis());
}*/
}
} catch (Exception e) {
}
}*/
}
if (Objects.isNull(device)) {
log.warn("device:{} is not found.", deviceName);
} else {
@ -127,7 +153,8 @@ public class ThingServiceImpl implements IThingService {
System.out.println("type+++++++++++++++++++++" + type);
System.out.println("action+++++++++++++++++++++" + action);
System.out.println("device+++++++++++++++++++++" + device);
switch (type) {
switch (type) {
case REGISTER:
//设备注册
String deviceId = registerDevice(device, (DeviceRegister) action, null);
@ -178,6 +205,10 @@ public class ThingServiceImpl implements IThingService {
case PROPERTY_REPORT:
//属性上报
PropertyReport propertyReport = (PropertyReport) action;
//根据事件变更设备状态,如果是浓度需要额外添加到指定表
Map map = propertyReport.getParams();
deviceStatusUpdate(device, map);
publishMsg(
device, action,
ThingModelMessage.builder()
@ -185,12 +216,11 @@ public class ThingServiceImpl implements IThingService {
.identifier(ThingModelMessage.ID_PROPERTY_REPORT)
.data(propertyReport.getParams())
.time(propertyReport.getTime())
.deviceStatus(device.getDeviceStatus())
.occurred(propertyReport.getTime())
.build()
);
//根据事件变更设备状态,如果是浓度需要额外添加到指定表
Map map = propertyReport.getParams();
deviceStatusUpdate(device, map);
break;
@ -249,37 +279,44 @@ public class ThingServiceImpl implements IThingService {
if (!status.equals(1) && !status.equals(2)) {
device.setDeviceStatus(0);
}
List<DeviceInfo> deviceInfoArrayList = new ArrayList<>();
boolean success = false;
//设备在线发生了故障或者报警
if (state.isOnline()) {
if (isMapValid(map, "eventTypeValue")) {
if (map.get("eventTypeValue").toString().contains("寿命到期")) {
device.setDeviceStatus(4);
}
if (map.get("eventTypeValue").toString().contains("故障") && !map.get("eventTypeValue").toString().contains("故障恢复")) {
if (!status.equals(2) && map.get("eventTypeValue").toString().contains("故障") && !map.get("eventTypeValue").toString().contains("故障恢复")) {
device.setDeviceStatus(1);
} else if (map.get("eventTypeValue").toString().contains("故障恢复")) {
success = true;
} else if ( !status.equals(2) && map.get("eventTypeValue").toString().contains("故障恢复")) {
device.setDeviceStatus(0);
}
// if(device.getDeviceName().equals("864029082017629") || device.getDeviceName().equals("864029082017017")){
if (map.get("eventTypeValue").toString().contains("警") && !map.get("eventTypeValue").toString().contains("正常") && !map.get("eventTypeValue").toString().contains("报警恢复")) {
//如果该区域有控制箱,设备发生告警发送控制箱控制
try {
deviceLinkageControl(device);
}catch (Exception e){
log.error("设备控制异常",e);
deviceInfoArrayList = deviceLinkageControl(device);
} catch (Exception e) {
log.error("设备控制异常", e);
}
success = true;
device.setDeviceStatus(2);
}
} else if (map.get("eventTypeValue").toString().contains("报警恢复")) {
device.setDeviceStatus(0);
deviceLinkageControl1(device);
}
if (map.get("eventTypeValue").toString().contains("自检完成") ||
map.get("eventTypeValue").toString().contains("预热完成") ||
map.get("eventTypeValue").toString().contains("控制器复位") ||
map.get("eventTypeValue").toString().contains("控制器开机")) {
device.setDeviceStatus(0);
deviceLinkageControl1(device);
}
}
} else {
// }
if (!state.isOnline()) {
if (!status.equals(1) && !status.equals(2)) {
device.setDeviceStatus(3);
}
@ -288,74 +325,221 @@ public class ThingServiceImpl implements IThingService {
if (ObjectUtil.isNotNull(device.getDeviceStatus()) && !status.equals(device.getDeviceStatus())) {
deviceInfoData.save(device);
}
if (success) {
ThingModelMessage thingModelMessage = ThingModelMessage.builder()
.type(ThingModelMessage.TYPE_PROPERTY)
.identifier(ThingModelMessage.ID_PROPERTY_REPORT)
.data(map)
.deviceId(device.getDeviceId())
.deviceName(device.getDeviceName())
.productKey(device.getProductKey())
.time(System.currentTimeMillis())
.deviceStatus(device.getDeviceStatus())
.occurred(System.currentTimeMillis())
.build();
List<AlertConfig> config = iAlertConfigData.findByDeviceName(device.getDeviceName());
/* if(config.isEmpty()){
List<Rule> rules = ruleMessageHandler.processMessage1(thingModelMessage);
for (Rule rule : rules) {
config = iAlertConfigData.findByRuleInfoId(rule.getId());
}
}*/
// List<AlertRecord> alerts = idAlertRecordData.selectAlertConfigPage(AlertRecordBo.builder().details(device.getDeviceName()).build());
System.out.println("设备告警 您的设备【" + device.getDeviceName() + "】触发事件 事件类型为:【" + map.get("eventTypeValue").toString() + "】。");
if (ObjectUtil.isEmpty(config)) {
try {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<DeviceInfo> deviceInfoArrayList1 = deviceInfoArrayList;
executor.execute(() -> {
List<Rule> rules = ruleMessageHandler.processMessage1(thingModelMessage);
for (Rule rule : rules) {
List<AlertConfig> config1 = iAlertConfigData.findByRuleInfoId(rule.getId());
for (int i = 0; i < config1.size(); i++) {
idAlertRecordData.save(AlertRecord.builder()
.level(config1.get(i).getLevel())
.name(config1.get(i).getName())
.tenantId(device.getTenantId())
.uid(device.getUid())
.deptAreaId(device.getDeptAreaId())
.readFlg(false)
.alertTime(System.currentTimeMillis())
.details("您的设备【" + device.getDeviceName() + "】触发事件 事件类型为:【" + map.get("eventTypeValue").toString() + "】。")
.build());
if (ObjectUtil.isNotEmpty(deviceInfoArrayList1)) {
for (int j = 0; j < deviceInfoArrayList1.size(); j++) {
String deviceName = deviceInfoArrayList1.get(j).getNodeStatus().equals("1")?device.getDeviceName(): deviceInfoArrayList1.get(j).getNodeDevice();
idAlertRecordData.save(AlertRecord.builder()
.level(config1.get(i).getLevel())
.name(config1.get(i).getName())
.tenantId(deviceInfoArrayList1.get(j).getTenantId())
.uid(deviceInfoArrayList1.get(j).getUid())
.deptAreaId(deviceInfoArrayList1.get(j).getDeptAreaId())
.readFlg(false)
.alertTime(System.currentTimeMillis())
.details("您的设备【" + deviceInfoArrayList1.get(j).getDeviceName() + "】,节点" + deviceInfoArrayList1.get(j).getNode() + "触发事件,事件类型:【联动箱输出】," + "告警设备:" + deviceName)
.build());
}
}
ruleExecutor.execute1(thingModelMessage, config1);
}
}
// RuleExecutor ruleExecutor = new RuleExecutor();
});
executor.shutdown(); // 触发线程池关闭
} catch (Exception e) {
}
} else {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<DeviceInfo> deviceInfoArrayList1 = deviceInfoArrayList;
executor.execute(() -> {
for (int i = 0; i < config.size(); i++) {
idAlertRecordData.save(AlertRecord.builder()
.level(config.get(i).getLevel())
.name(config.get(i).getName())
.tenantId(device.getTenantId())
.uid(device.getUid())
.deptAreaId(device.getDeptAreaId())
.readFlg(false)
.alertTime(System.currentTimeMillis())
.details("您的设备【" + device.getDeviceName() + "】触发事件 事件类型为:【" + map.get("eventTypeValue").toString() + "】。")
.build());
if (ObjectUtil.isNotEmpty(deviceInfoArrayList1)) {
for (int j = 0; j < deviceInfoArrayList1.size(); j++) {
String deviceName = deviceInfoArrayList1.get(j).getNodeStatus().equals("1")?device.getDeviceName(): deviceInfoArrayList1.get(j).getNodeDevice();
idAlertRecordData.save(AlertRecord.builder()
.level(config.get(i).getLevel())
.name(config.get(i).getName())
.tenantId(deviceInfoArrayList1.get(j).getTenantId())
.uid(deviceInfoArrayList1.get(j).getUid())
.deptAreaId(deviceInfoArrayList1.get(j).getDeptAreaId())
.readFlg(false)
.alertTime(System.currentTimeMillis())
.details("您的设备【" + deviceInfoArrayList1.get(j).getDeviceName() + "】,节点" + deviceInfoArrayList1.get(j).getNode() + "触发事件,事件类型:【联动箱输出】," + "告警设备:" + deviceName)
.build());
}
}
ruleExecutor.execute1(thingModelMessage, config);
}
// RuleExecutor ruleExecutor = new RuleExecutor();
});
}
}
//存入浓度变化
extractDetectorData(device, map);
}
/**
* ,
* */
private void deviceLinkageControl(DeviceInfo device) {
*/
private List<DeviceInfo> deviceLinkageControl(DeviceInfo device) {
List<DeviceInfo> deviceInfo1 = new ArrayList<>();
deviceInfo1 = getDeviceInfo(device.getDeptAreaId(),"MQFejp7cyDMH3enG");
if(deviceInfo1 != null && !deviceInfo1.isEmpty()) {
deviceInfo1 = getDeviceInfo(device.getDeptAreaId(), "MQFejp7cyDMH3enG");
Boolean flag = false;
String nodeStatus = null;
List<DeviceInfo> deviceInfo55 = new ArrayList<>();
if (deviceInfo1 != null && !deviceInfo1.isEmpty()) {
for (DeviceInfo deviceInfo2 : deviceInfo1) {
if(ObjectUtil.isNotNull(deviceInfo2.getNodeOne()) && ObjectUtil.isNotNull(deviceInfo2.getNodeOneStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeOneDevice())) {
if (deviceInfo2.getNodeOneStatus().equals("1")) {
//选中的任意一个设备报警就发送联动控制指令
deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeOne());
}else{
//满足所有的设备告警才触发联动控制
String [] nodeOneDevice = deviceInfo2.getNodeOneDevice().split(",");
handleDeviceAlert(deviceInfo2,deviceInfo2.getNodeOne(),nodeOneDevice);
}
if (ObjectUtil.isNotNull(deviceInfo2.getNodeOne()) && ObjectUtil.isNotNull(deviceInfo2.getNodeOneStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeOneDevice())) {
flag = false;
if (deviceInfo2.getNodeOneStatus().equals("1")) {
//选中的任意一个设备报警就发送联动控制指令
flag = deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeOne());
} else {
//满足所有的设备告警才触发联动控制
String[] nodeOneDevice = deviceInfo2.getNodeOneDevice().split(",");
//
flag = handleDeviceAlert(device,deviceInfo2, deviceInfo2.getNodeOne(), nodeOneDevice);
}
nodeStatus = "1";
if (flag) {
deviceInfo2.setNode(nodeStatus);
deviceInfo2.setNodeStatus(deviceInfo2.getNodeOneStatus());
deviceInfo2.setNodeDevice(deviceInfo2.getNodeOneDevice());
deviceInfo55.add(deviceInfo2);
}
}
if(ObjectUtil.isNotNull(deviceInfo2.getNodeTwo()) && ObjectUtil.isNotNull(deviceInfo2.getNodeTwoStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeTwoDevice())) {
if (ObjectUtil.isNotNull(deviceInfo2.getNodeTwo()) && ObjectUtil.isNotNull(deviceInfo2.getNodeTwoStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeTwoDevice())) {
//deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeTwo());
flag = false;
if (deviceInfo2.getNodeTwoStatus().equals("1")) {
//选中的任意一个设备报警就发送联动控制指令
deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeTwo());
}else{
flag = deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeTwo());
} else {
//满足所有的设备告警才触发联动控制
String [] nodeOneDevice = deviceInfo2.getNodeTwoDevice().split(",");
handleDeviceAlert(deviceInfo2,deviceInfo2.getNodeTwo(),nodeOneDevice);
String[] nodeOneDevice = deviceInfo2.getNodeTwoDevice().split(",");
flag = handleDeviceAlert(device,deviceInfo2, deviceInfo2.getNodeTwo(), nodeOneDevice);
}
nodeStatus = "2";
if (flag) {
deviceInfo2.setNode(nodeStatus);
deviceInfo2.setNodeStatus(deviceInfo2.getNodeTwoStatus());
deviceInfo2.setNodeDevice(deviceInfo2.getNodeTwoDevice());
deviceInfo55.add(deviceInfo2);
}
}
if(ObjectUtil.isNotNull(deviceInfo2.getNodeThree()) && ObjectUtil.isNotNull(deviceInfo2.getNodeThreeStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeThreeDevice())) {
// deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeThree());
if (ObjectUtil.isNotNull(deviceInfo2.getNodeThree()) && ObjectUtil.isNotNull(deviceInfo2.getNodeThreeStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeThreeDevice())) {
// deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeThree());
flag = false;
if (deviceInfo2.getNodeThreeStatus().equals("1")) {
//选中的任意一个设备报警就发送联动控制指令
deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeThree());
}else{
flag = deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeThree());
} else {
//满足所有的设备告警才触发联动控制
String [] nodeOneDevice = deviceInfo2.getNodeThreeDevice().split(",");
handleDeviceAlert(deviceInfo2,deviceInfo2.getNodeThree(),nodeOneDevice);
String[] nodeOneDevice = deviceInfo2.getNodeThreeDevice().split(",");
flag = handleDeviceAlert(device,deviceInfo2, deviceInfo2.getNodeThree(), nodeOneDevice);
}
nodeStatus = "3";
if (flag) {
deviceInfo2.setNode(nodeStatus);
deviceInfo2.setNodeStatus(deviceInfo2.getNodeThreeStatus());
deviceInfo2.setNodeDevice(deviceInfo2.getNodeThreeDevice());
deviceInfo55.add(deviceInfo2);
}
}
if(ObjectUtil.isNotNull(deviceInfo2.getNodeFour()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFourStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFourDevice())) {
// deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeFour());
if (ObjectUtil.isNotNull(deviceInfo2.getNodeFour()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFourStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFourDevice())) {
// deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeFour());
flag = false;
if (deviceInfo2.getNodeFourStatus().equals("1")) {
//选中的任意一个设备报警就发送联动控制指令
deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeFour());
}else{
flag = deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeFour());
} else {
//满足所有的设备告警才触发联动控制
String [] nodeOneDevice = deviceInfo2.getNodeFourDevice().split(",");
handleDeviceAlert(deviceInfo2,deviceInfo2.getNodeFour(),nodeOneDevice);
String[] nodeOneDevice = deviceInfo2.getNodeFourDevice().split(",");
flag = handleDeviceAlert(device,deviceInfo2, deviceInfo2.getNodeFour(), nodeOneDevice);
}
nodeStatus = "4";
if (flag) {
deviceInfo2.setNode(nodeStatus);
deviceInfo2.setNodeStatus(deviceInfo2.getNodeFourStatus());
deviceInfo2.setNodeDevice(deviceInfo2.getNodeFourDevice());
deviceInfo55.add(deviceInfo2);
}
}
if(ObjectUtil.isNotNull(deviceInfo2.getNodeFive()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFiveStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFiveDevice())) {
// deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeFive());
if (ObjectUtil.isNotNull(deviceInfo2.getNodeFive()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFiveStatus()) && ObjectUtil.isNotNull(deviceInfo2.getNodeFiveDevice())) {
// deviceLinkageControlSend(deviceInfo2,deviceInfo2.getNodeFive());
flag = false;
if (deviceInfo2.getNodeFiveStatus().equals("1")) {
//选中的任意一个设备报警就发送联动控制指令
deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeFive());
}else{
flag = deviceLinkageControlSend(deviceInfo2, deviceInfo2.getNodeFive());
} else {
//满足所有的设备告警才触发联动控制
String [] nodeOneDevice = deviceInfo2.getNodeFiveDevice().split(",");
handleDeviceAlert(deviceInfo2,deviceInfo2.getNodeFive(),nodeOneDevice);
String[] nodeOneDevice = deviceInfo2.getNodeFiveDevice().split(",");
flag = handleDeviceAlert(device,deviceInfo2, deviceInfo2.getNodeFive(), nodeOneDevice);
}
nodeStatus = "5";
if (flag) {
deviceInfo2.setNode(nodeStatus);
deviceInfo2.setNodeStatus(deviceInfo2.getNodeFiveStatus());
deviceInfo2.setNodeDevice(deviceInfo2.getNodeFiveDevice());
deviceInfo55.add(deviceInfo2);
}
}
}
}
return deviceInfo55;
/* //下发联动控制箱控制输出
send(device.getDeviceId(), device.getProductKey(), device.getDeviceName(),
Map.of(
@ -380,24 +564,52 @@ public class ThingServiceImpl implements IThingService {
}
private void deviceLinkageControl1(DeviceInfo device) {
try {
List<DeviceInfo> deviceInfo1 = getDeviceInfo(device.getDeptAreaId(), "MQFejp7cyDMH3enG");
for (DeviceInfo deviceInfo2 : deviceInfo1) {
String ALERT_MAP_KEY1 = "device:alert:map" + ":" + "0001" + ":" + deviceInfo2.getDeviceName();
String ALERT_MAP_KEY2 = "device:alert:map" + ":" + "0002" + ":" + deviceInfo2.getDeviceName();
String ALERT_MAP_KEY3 = "device:alert:map" + ":" + "0003" + ":" + deviceInfo2.getDeviceName();
String ALERT_MAP_KEY4 = "device:alert:map" + ":" + "0004" + ":" + deviceInfo2.getDeviceName();
String ALERT_MAP_KEY5 = "device:alert:map" + ":" + "0005" + ":" + deviceInfo2.getDeviceName();
delCacheMapValue(ALERT_MAP_KEY1, device.getDeviceName());
delCacheMapValue(ALERT_MAP_KEY2, device.getDeviceName());
delCacheMapValue(ALERT_MAP_KEY3, device.getDeviceName());
delCacheMapValue(ALERT_MAP_KEY4, device.getDeviceName());
delCacheMapValue(ALERT_MAP_KEY5, device.getDeviceName());
}
}catch (Exception e ){
log.error("设备联动异常删除缓存",e);
}
public void handleDeviceAlert(DeviceInfo deviceInfo,String node,String[] device) {
String ALERT_MAP_KEY = "device:alert:map" +":" +node;
// 记录设备告警状态
setCacheMapValue(ALERT_MAP_KEY, deviceInfo.getDeviceName(), System.currentTimeMillis());
// 获取当前告警设备数
RMap<String, Long> alertMap = RedisUtils.getClient().getMap(ALERT_MAP_KEY);
if (alertMap.size() >= device.length) {
deviceLinkageControlSend(deviceInfo,node);
// triggerCommand(new ArrayList<>(alertMap.keySet()));
alertMap.clear();
}
}
public boolean handleDeviceAlert(DeviceInfo deviceInfo1,DeviceInfo deviceInfo, String node, String[] device) {
boolean isAlert = false;
boolean isContained = Arrays.asList(device).contains(deviceInfo1.getDeviceName());
if(!isContained){
return isAlert;
}
String ALERT_MAP_KEY = "device:alert:map" + ":" + node + ":" + deviceInfo.getDeviceName();
// 记录设备告警状态
setCacheMapValue(ALERT_MAP_KEY, deviceInfo1.getDeviceName(), deviceInfo1.getDeviceName());
// expire(ALERT_MAP_KEY, 172800);
// 获取当前告警设备数
RMap<String, Long> alertMap = RedisUtils.getClient().getMap(ALERT_MAP_KEY);
//删除某个key delCacheMapValue(ALERT_MAP_KEY, "862571079391303");
if (alertMap.size() >= device.length || alertMap.size() >= 2) {
isAlert = deviceLinkageControlSend(deviceInfo, node);
// triggerCommand(new ArrayList<>(alertMap.keySet()));
alertMap.clear();
}
return isAlert;
}
private void deviceLinkageControlSend(DeviceInfo device,String node) {
private boolean deviceLinkageControlSend(DeviceInfo device, String node) {
ThingService<Object> thingService = ThingService.builder()
.mid(UniqueIdUtil.newRequestId())
.productKey(device.getProductKey())
@ -410,11 +622,14 @@ public class ThingServiceImpl implements IThingService {
.build();
//联动控制箱下发指令
deviceService.invoke(thingService);
return true;
}
//浓度变化
public void extractDetectorData(DeviceInfo device, Map<String, Object> baseInfo) {
for (Map.Entry<String, Object> entry : baseInfo.entrySet()) {
if (entry.getKey().startsWith("dataDetectorValue")) {
String suffix = entry.getKey().substring(17); // 去掉前缀"dataDetectorValue"
String value = entry.getValue().toString();
// 获取对应节点信息
@ -433,6 +648,14 @@ public class ThingServiceImpl implements IThingService {
}
if (ObjectUtil.isNotNull(baseInfo.get(gasTypeKey))) {
detectorInfo.setGasTypeKey(baseInfo.get(gasTypeKey).toString());
}
if (ObjectUtil.isNotNull(baseInfo.get("eventTypeValue"))) {
if (baseInfo.get("eventTypeValue").toString().contains("控制器复位") || baseInfo.get("eventTypeValue").toString().contains("控制器开机")) {
detectorInfo.setNodeContext("正常");
} else {
detectorInfo.setNodeContext(baseInfo.get("eventTypeValue").toString());
}
}
iDeviceDetectorInfoData.save(detectorInfo);
/*
@ -480,20 +703,23 @@ public class ThingServiceImpl implements IThingService {
public DeviceInfo getDeviceInfo(String dn) {
try {
return deviceInfoData.findByDeviceName(dn);
} catch (Throwable e) {
log.error("get device error", e);
return null;
}
}
public List<DeviceInfo> getDeviceInfo(Long areaDeptId,String productKey) {
public List<DeviceInfo> getDeviceInfo(Long areaDeptId, String productKey) {
try {
return deviceInfoData.findByDeptAreaIdAndProductKey(areaDeptId,productKey);
return deviceInfoData.findByDeptAreaIdAndProductKey(areaDeptId, productKey);
} catch (Throwable e) {
log.error("get device error", e);
return null;
}
}
@Override
public ThingDevice getDevice(String dn) {
DeviceInfo deviceInfo = getDeviceInfo(dn);
@ -594,6 +820,7 @@ public class ThingServiceImpl implements IThingService {
}
if (device != null) {
device.setDeviceStatus(0);
//随便写写
if (params != null && !params.isEmpty()) {
if (ObjectUtil.isNotNull(params.get("signalStrength"))) {

@ -1,9 +1,15 @@
package cc.iotkit.ruleengine.config;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CallRateLimiter {
private static final String REDIS_KEY_PREFIX = "call:limit:";
@ -29,6 +35,7 @@ public class CallRateLimiter {
dayCount.get() <= 20;
}
public static void main(String[] args) {
System.out.println(CallRateLimiter.checkRateLimit("19118345694"));;
}

@ -29,17 +29,23 @@ import cc.iotkit.common.utils.JsonUtils;
import cc.iotkit.common.utils.ThreadUtil;
import cc.iotkit.mq.ConsumerHandler;
import cc.iotkit.mq.MqConsumer;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
public class RuleDeviceConsumer implements ConsumerHandler<ThingModelMessage>, ApplicationContextAware {
@ -47,11 +53,31 @@ public class RuleDeviceConsumer implements ConsumerHandler<ThingModelMessage>, A
private final List<DeviceMessageHandler> handlers = new ArrayList<>();
private ScheduledThreadPoolExecutor messageHandlerPool;
//private ThreadPoolExecutor messageHandlerPool;
@SneakyThrows
public RuleDeviceConsumer(MqConsumer<ThingModelMessage> consumer) {
consumer.consume(Constants.THING_MODEL_MESSAGE_TOPIC, this);
}
/* @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, DeviceMessageHandler> handlerMap = applicationContext.getBeansOfType(DeviceMessageHandler.class);
// 动态计算核心线程数
int corePoolSize = Math.max(4, Runtime.getRuntime().availableProcessors());
// corePoolSize = corePoolSize > handlerMap.size()?corePoolSize:handlerMap.size();
int maxPoolSize = corePoolSize * 2;
messageHandlerPool = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10), // 限制队列大小
new ThreadFactoryBuilder().setNameFormat("msg-handler-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 饱和策略
);
this.handlers.addAll(handlerMap.values());
}*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, DeviceMessageHandler> handlerMap = applicationContext.getBeansOfType(DeviceMessageHandler.class);

@ -100,8 +100,83 @@ public class RuleExecutor {
@Resource
private WxMaService wxMaService;
public void execute1(ThingModelMessage message,List<AlertConfig> listAlertConfigs) {
DeviceInfo deviceInfo = iDeviceInfoData.findByDeviceId(message.getDeviceId());
// 注入 WxMaService 后直接调用
String appId = wxMaService.getWxMaConfig().getAppid();
System.out.println("当前小程序AppID: " + appId);
Map<String, Object> alertData = message.dataToMap();
System.out.println("messagePushalertData+++++++++++++++++++++++++++++" + alertData);
// String alertData = processData(message);
// String deviceName = message.getDeviceName();
try {
// DeviceInfo deviceInfo = iDeviceInfoData.findByDeviceId(message.getDeviceId());
if (ObjectUtil.isNotNull(deviceInfo)) {
UserInfo userInfo = new UserInfo();
if(ObjectUtil.isNotNull(deviceInfo.getUid()) && !deviceInfo.getUid().equals("")){
userInfo = iUserInfoData.findById(Long.valueOf(deviceInfo.getUid()));
if (ObjectUtil.isNull(userInfo)) {
return;
}
}
// List<AlertConfig> listAlertConfigs = iAlertConfigData.findByUidAndRuleInfoIdAndDeviceName(deviceInfo.getUid(), ruleLog.getRuleId(), deviceInfo.getDeviceName());
for (AlertConfig alertConfig : listAlertConfigs) {
if (ObjectUtil.isNotNull(alertConfig.getMessagePushIpone())) {
String[] messagePushIpone = alertConfig.getMessagePushIpone().split(",");
// System.out.println("messagePushIpone+++++++++++++++++++++++++++++" + messagePushIpone);
// System.out.println("messagePushIpone.length+++++++++++++++++++++++++++++" + messagePushIpone.length);
for (int i = 0; i < messagePushIpone.length; i++) {
if (isValid(messagePushIpone[i])) {
String[] messagePush = alertConfig.getMessagePush().split(",");
UserInfo userInfo1 = new UserInfo();
userInfo1.setUserName(messagePushIpone[i]);
if(ObjectUtil.isNotNull(userInfo) && ObjectUtil.isNotNull(userInfo.getUid())) {
userInfo1.setUid(userInfo.getUid());
}
sendMessage(messagePush, message, deviceInfo, userInfo1, alertData, alertConfig, i);
}
}
} else {
String[] messagePush = alertConfig.getMessagePush().split(",");
// System.out.println("messagePush+++++++++++++++++++++++++++++" + messagePush);
sendMessage(messagePush, message, deviceInfo, userInfo, alertData, alertConfig, 0);
}
}
}
} catch (Exception e) {
}
}
public void execute(ThingModelMessage message, Rule rule) {
log.info("The listener did not match the appropriate content,deviceStatus:{},{}", rule.getId(), message.getDeviceStatus());
if(ObjectUtil.isNull(message.getDeviceStatus())
|| message.getDeviceStatus().equals(2) ||
message.getDeviceStatus().equals(1)
){
List<AlertConfig> config = iAlertConfigData.findByDeviceName(message.getDeviceName());
log.info("The listener did not match the appropriate content,deviceStatus:{},{}", rule.getId(), message.getDeviceStatus());
if(!config.isEmpty()){
return;
}else{
List<AlertConfig> config1 = iAlertConfigData.findByRuleInfoId(rule.getId());
if(!config1.isEmpty()){
return;
}
}
}
if (!doListeners(message, rule)) {
/* if(ObjectUtil.isNotNull(message.getDeviceStatus())
&& (message.getDeviceStatus().equals(1) || message.getDeviceStatus().equals(2))
) {
log.info("继续处理规则");
}else{*/
// return;
// }
log.info("The listener did not match the appropriate content,rule:{},{}", rule.getId(), rule.getName());
return;
}
@ -145,9 +220,12 @@ public class RuleExecutor {
try {
// DeviceInfo deviceInfo = iDeviceInfoData.findByDeviceId(message.getDeviceId());
if (ObjectUtil.isNotNull(deviceInfo) && ObjectUtil.isNotNull(deviceInfo.getUid())) {
UserInfo userInfo = iUserInfoData.findById(Long.valueOf(deviceInfo.getUid()));
if (ObjectUtil.isNull(userInfo)) {
return;
UserInfo userInfo = new UserInfo();
if(ObjectUtil.isNotNull(deviceInfo.getUid()) && !deviceInfo.getUid().equals("")){
userInfo = iUserInfoData.findById(Long.valueOf(deviceInfo.getUid()));
if (ObjectUtil.isNull(userInfo)) {
return;
}
}
List<AlertConfig> listAlertConfigs = iAlertConfigData.findByUidAndRuleInfoIdAndDeviceName(deviceInfo.getUid(), ruleLog.getRuleId(), deviceInfo.getDeviceName());
@ -161,7 +239,9 @@ public class RuleExecutor {
String[] messagePush = alertConfig.getMessagePush().split(",");
UserInfo userInfo1 = new UserInfo();
userInfo1.setUserName(messagePushIpone[i]);
userInfo1.setUid(userInfo.getUid());
if(ObjectUtil.isNotNull(userInfo) && ObjectUtil.isNotNull(userInfo.getUid())) {
userInfo1.setUid(userInfo.getUid());
}
sendMessage(messagePush, message, deviceInfo, userInfo1, alertData, alertConfig, i);
}
}
@ -183,7 +263,6 @@ public class RuleExecutor {
ruleLogData.add(ruleLog);
}
}
public boolean isValid(String phone) {
return phone != null && phone.matches("^\\d{11}$");
}

@ -28,9 +28,11 @@ import cc.iotkit.ruleengine.action.alert.AlertService;
import cc.iotkit.ruleengine.handler.DeviceMessageHandler;
import cc.iotkit.ruleengine.listener.DeviceCondition;
import cc.iotkit.ruleengine.listener.Listener;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.tomcat.util.digester.Rules;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.*;
@ -44,6 +46,7 @@ import java.util.regex.Pattern;
public class RuleMessageHandler implements DeviceMessageHandler {
private final ConcurrentMap<String, List<Rule>> deviceRuleMap = new ConcurrentHashMap<>();
// 全局唯一线程池配置
@Autowired
@ -96,7 +99,7 @@ public class RuleMessageHandler implements DeviceMessageHandler {
Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors() * 2,
60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10000),
new ArrayBlockingQueue<>(1000),
new ThreadPoolExecutor.CallerRunsPolicy());
}
@ -183,6 +186,43 @@ public class RuleMessageHandler implements DeviceMessageHandler {
}
public List<Rule> processMessage1(ThingModelMessage message) {
// Rule[] rules = getRulesForMessage(message);
String pk = message.getProductKey();
String dn = message.getDeviceName();
List<Rule> rules = new ArrayList<>();
//仅用PK匹配
List<Rule> foundRules = deviceRuleMap.get(pk + "/#");
if (foundRules != null) {
if (foundRules.get(0).getListeners().size() == 1) {
rules.add(foundRules.get(0));
} else {
rules.addAll(foundRules);
}
}
//用PK和DN匹配
foundRules = deviceRuleMap.get(pk + "/" + dn);
if (foundRules != null) {
if (foundRules.get(0).getListeners().size() == 1) {
rules.add(foundRules.get(0));
} else {
rules.addAll(foundRules);
}
// rules.addAll(foundRules);
}
/* for (Rule rule : rules) {
rule
clearUnmatchedScripts(rule, message, tempServices);
ruleExecutor.execute1(message, rule);
}*/
return rules;
}
private Rule[] getRulesForMessage(ThingModelMessage message) {
String pk = message.getProductKey();

@ -63,13 +63,13 @@ public class SysTenantBo extends BaseDto {
/**
*
*/
@NotBlank(message = "联系人不能为空", groups = { AddGroup.class, EditGroup.class })
//@NotBlank(message = "联系人不能为空", groups = { AddGroup.class, EditGroup.class })
private String contactUserName;
/**
*
*/
@NotBlank(message = "联系电话不能为空", groups = { AddGroup.class, EditGroup.class })
// @NotBlank(message = "联系电话不能为空", groups = { AddGroup.class, EditGroup.class })
private String contactPhone;
/**

Loading…
Cancel
Save