package cc.iotkit.data.service; import cc.iotkit.common.api.PageRequest; import cc.iotkit.common.api.Paging; import cc.iotkit.common.utils.MapstructUtils; import cc.iotkit.common.utils.ReflectUtil; import cc.iotkit.data.dao.*; import cc.iotkit.data.manager.ICategoryData; import cc.iotkit.data.manager.IDeviceInfoData; import cc.iotkit.data.manager.IProductData; import cc.iotkit.data.model.*; import cc.iotkit.data.util.PageBuilder; import cc.iotkit.data.util.PredicateBuilder; import cc.iotkit.model.device.DeviceInfo; import cc.iotkit.model.device.message.DevicePropertyCache; import cc.iotkit.model.product.Category; import cc.iotkit.model.product.Product; import cc.iotkit.model.stats.DataItem; import cn.hutool.core.collection.CollectionUtil; import com.querydsl.core.Tuple; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.data.domain.Page; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; import static cc.iotkit.data.model.QTbDeviceGroupMapping.tbDeviceGroupMapping; import static cc.iotkit.data.model.QTbDeviceInfo.tbDeviceInfo; import static cc.iotkit.data.model.QTbDeviceSubUser.tbDeviceSubUser; import static cc.iotkit.data.model.QTbProduct.tbProduct; @Primary @Service @RequiredArgsConstructor public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData { private final DeviceInfoRepository deviceInfoRepository; private final DeviceSubUserRepository deviceSubUserRepository; private final DeviceGroupMappingRepository deviceGroupMappingRepository; private final DeviceGroupRepository deviceGroupRepository; private final DeviceTagRepository deviceTagRepository; @Qualifier("productDataCache") private final IProductData productData; @Qualifier("categoryDataCache") private final ICategoryData categoryData; private final JPAQueryFactory jpaQueryFactory; private List deviceStateList = Arrays.asList("online", "offline", "unactivated"); @Override public JpaRepository getBaseRepository() { return deviceInfoRepository; } @Override public Class getJpaRepositoryClass() { return TbDeviceInfo.class; } @Override public Class getTClass() { return DeviceInfo.class; } @Override public void saveProperties(String deviceId, Map properties) { } @Override public Map getProperties(String deviceId) { return new HashMap<>(); } @Override public DeviceInfo findByDeviceId(String deviceId) { TbDeviceInfo tbDeviceInfo = deviceInfoRepository.findByDeviceId(deviceId); DeviceInfo dto = MapstructUtils.convert(tbDeviceInfo, DeviceInfo.class); fillDeviceInfo(deviceId, tbDeviceInfo, dto); return dto; } /** * 填充设备其它信息 */ private void fillDeviceInfo(String deviceId, TbDeviceInfo vo, DeviceInfo dto) { if (vo == null || dto == null) { return; } //取子关联用户 dto.setSubUid(deviceSubUserRepository.findByDeviceId(deviceId).stream() .map(TbDeviceSubUser::getUid).collect(Collectors.toList())); //取设备所属分组 List groupMappings = deviceGroupMappingRepository.findByDeviceId(deviceId); Map groups = new HashMap<>(); for (TbDeviceGroupMapping mapping : groupMappings) { TbDeviceGroup deviceGroup = deviceGroupRepository.findById(mapping.getGroupId()).orElse(null); if (deviceGroup == null) { continue; } groups.put(deviceGroup.getId(), new DeviceInfo.Group(deviceGroup.getId(), deviceGroup.getName())); } dto.setGroup(groups); //取设备标签 List deviceTags = deviceTagRepository.findByDeviceId(deviceId); Map tagMap = new HashMap<>(); for (TbDeviceTag tag : deviceTags) { tagMap.put(tag.getCode(), new DeviceInfo.Tag(tag.getCode(), tag.getName(), tag.getValue())); } dto.setTag(tagMap); //将设备状态从vo转为dto的 parseStateToDto(vo, dto); } /** * 将设备状态从vo转为dto的 */ private void parseStateToDto(TbDeviceInfo vo, DeviceInfo dto) { dto.setState(new DeviceInfo.State("online".equals(vo.getState()), vo.getOnlineTime(), vo.getOfflineTime())); dto.setLocate(new DeviceInfo.Locate(vo.getLongitude(), vo.getLatitude())); } /** * 将设备状态从dto转vo */ private void parseStateToVo(DeviceInfo dto, TbDeviceInfo vo) { DeviceInfo.State state = dto.getState(); vo.setState(state.isOnline() ? "online" : "offline"); vo.setOfflineTime(state.getOfflineTime()); vo.setOnlineTime(state.getOnlineTime()); DeviceInfo.Locate locate = dto.getLocate(); vo.setLongitude(locate.getLongitude()); vo.setLatitude(locate.getLatitude()); } /** * 将数据库中查出来的vo转为dto */ private DeviceInfo parseVoToDto(TbDeviceInfo vo) { if (vo == null) { return null; } DeviceInfo dto = MapstructUtils.convert(vo, DeviceInfo.class); fillDeviceInfo(vo.getDeviceId(), vo, dto); return dto; } /** * 将数据库中查出来的vo列表转为dto列表 */ private List parseVoToDto(List vos) { return vos.stream().map(d -> { DeviceInfo dto = MapstructUtils.convert(d, DeviceInfo.class); fillDeviceInfo(d.getDeviceId(), d, dto); return dto; }).collect(Collectors.toList()); } @Override public DeviceInfo findByDeviceName(String deviceName) { return parseVoToDto(deviceInfoRepository.findByDeviceName(deviceName)); } @Override public List findByParentId(String parentId) { return parseVoToDto(deviceInfoRepository.findByParentId(parentId)); } @Override public List findSubDeviceIds(String parentId) { return jpaQueryFactory.select(tbDeviceInfo.deviceId).from(tbDeviceInfo) .where(tbDeviceInfo.parentId.eq(parentId)).fetch(); } @Override public List findByProductNodeType(String uid) { List devices = jpaQueryFactory.select(tbDeviceInfo).from(tbDeviceInfo) .join(tbProduct).on(tbProduct.nodeType.eq(0).and(tbDeviceInfo.productKey.eq(tbProduct.productKey))).fetch(); return MapstructUtils.convert(devices, DeviceInfo.class); } @Override public boolean existByProductKey(String productKey) { return Optional.ofNullable(jpaQueryFactory.selectOne().from(tbDeviceInfo).where(tbDeviceInfo.productKey.eq(productKey)).fetchOne()).orElse(0) > 0; } @Override public Paging findByConditions(String uid, String subUid, String productKey, String groupId, String state, String keyword, int page, int size) { JPAQuery query = jpaQueryFactory.selectFrom(tbDeviceInfo); if (StringUtils.isNotBlank(uid)) { query.where(tbDeviceInfo.uid.eq(uid)); } 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 (StringUtils.isNotBlank(state)) { query.where(tbDeviceInfo.state.eq(state)); } if (StringUtils.isNotBlank(keyword)) { query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%") .or(tbDeviceInfo.deviceName.like("%" + keyword + "%"))); } query.orderBy(tbDeviceInfo.createAt.desc()); query.offset((page - 1) * size).limit(size); List tbDeviceInfos = query.fetch(); long total = query.fetchCount(); List 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 void updateTag(String deviceId, DeviceInfo.Tag tag) { TbDeviceTag deviceTag = deviceTagRepository.findByDeviceIdAndCode(deviceId, tag.getId()); if (deviceTag != null) { deviceTag.setName(tag.getName()); deviceTag.setValue(tag.getValue()); deviceTagRepository.save(deviceTag); } else { deviceTagRepository.save( TbDeviceTag.builder() .id(UUID.randomUUID().toString()) .code(tag.getId()) .deviceId(deviceId) .name(tag.getName()) .value(tag.getValue()) .build() ); } } @Override public List getDeviceStatsByCategory(String uid) { //先按产品统计设备数量 JPAQuery query = jpaQueryFactory.select(Projections.bean(DataItem.class, tbDeviceInfo.productKey, tbDeviceInfo.count())) .from(tbDeviceInfo) .groupBy(tbDeviceInfo.productKey); if (StringUtils.isNotBlank(uid)) { query.where(tbDeviceInfo.uid.eq(uid)); } List stats = new ArrayList<>(); List rst = query.fetch(); for (DataItem item : rst) { //找到产品对应的品类取出品类名 Product product = productData.findByProductKey(item.getName()); String cateId = product.getCategory(); Category category = categoryData.findById(cateId); if (category == null) { continue; } //将数据替换成按品类的数据 item.setName(category.getName()); } //按品类分组求合 rst.stream().collect(Collectors.groupingBy(DataItem::getName, Collectors.summarizingLong(item -> (long) item.getValue()))) .forEach((key, sum) -> stats.add(new DataItem(key, sum.getSum()))); return stats; } @Override public long countByGroupId(String groupId) { return deviceGroupMappingRepository.countByGroupId(groupId); } @Override @Transactional public void addToGroup(String deviceId, DeviceInfo.Group group) { String groupId = UUID.randomUUID().toString(); deviceGroupMappingRepository.save(new TbDeviceGroupMapping(groupId, deviceId, group.getId())); //更新设备数量 updateGroupDeviceCount(groupId); } private void updateGroupDeviceCount(String groupId) { //更新设备数量 TbDeviceGroup deviceGroup = deviceGroupRepository.findById(groupId).orElse(null); if (deviceGroup != null) { deviceGroup.setDeviceQty((int) countByGroupId(groupId)); deviceGroupRepository.save(deviceGroup); } } @Override public void updateGroup(String groupId, DeviceInfo.Group group) { //更新设备信息中的分组信息,关系数据库中不需要实现 } @Override @Transactional public void removeGroup(String deviceId, String groupId) { jpaQueryFactory.delete(tbDeviceGroupMapping) .where(tbDeviceGroupMapping.deviceId.eq(deviceId) .and(tbDeviceGroupMapping.groupId.eq(groupId))) .execute(); //更新设备数量 updateGroupDeviceCount(groupId); } @Override @Transactional public void removeGroup(String groupId) { jpaQueryFactory.delete(tbDeviceGroupMapping) .where(tbDeviceGroupMapping.groupId.eq(groupId)) .execute(); //更新设备数量 updateGroupDeviceCount(groupId); } @Override public List findByUid(String uid) { return new ArrayList<>(); } @Override public Paging findByUid(String uid, int page, int size) { return new Paging<>(); } @Override public long countByUid(String uid) { return 0; } @Override public DeviceInfo findById(String s) { return MapstructUtils.convert( deviceInfoRepository.findById(s).orElse(null), DeviceInfo.class); } @Override public List findByIds(Collection ids) { return MapstructUtils.convert(deviceInfoRepository.findAllById(ids), DeviceInfo.class); } @Override @Transactional public DeviceInfo save(DeviceInfo data) { TbDeviceInfo vo = deviceInfoRepository.findByDeviceId(data.getDeviceId()); if (StringUtils.isBlank(data.getId())) { data.setId(UUID.randomUUID().toString()); } if (vo == null) { vo = new TbDeviceInfo(); } ReflectUtil.copyNoNulls(data, vo); //状态转换 parseStateToVo(data, vo); //保存设备信息 deviceInfoRepository.save(vo); //设备分组转换 Map groupMap = data.getGroup(); groupMap.forEach((id, group) -> { TbDeviceGroupMapping mapping = deviceGroupMappingRepository.findByDeviceIdAndGroupId(data.getDeviceId(), id); if (mapping == null) { //保存设备分组与设备对应关系 deviceGroupMappingRepository.save(new TbDeviceGroupMapping( UUID.randomUUID().toString(), data.getDeviceId(), id )); } }); return data; } @Override public void batchSave(List data) { } @Override public void deleteById(String s) { deviceInfoRepository.deleteById(s); } @Override public void deleteByIds(Collection ids) { deviceInfoRepository.deleteAllById(ids); } @Override public long count() { return deviceInfoRepository.count(); } @Override public List findAll() { return new ArrayList<>(); } @Override public Paging findAll(PageRequest pageRequest) { Page ret = deviceInfoRepository.findAll(PageBuilder.toPageable(pageRequest)); return new Paging<>(ret.getTotalElements(), MapstructUtils.convert(ret.getContent(), DeviceInfo.class)); } @Override public List findAllByCondition(DeviceInfo data) { return Collections.emptyList(); } @Override public DeviceInfo findOneByCondition(DeviceInfo data) { return null; } @Override public Map countStateMap(String tenantId) { Map resultMap = new HashMap(); // if (StringUtils.isNotBlank(tenantId) && tenantId.equals("000000")) { // resultMap = countStateMapWithoutTenantId(); // } else { if (StringUtils.isNotBlank(tenantId)) { resultMap = countStateMapWithTenantId(tenantId); } // } for(String item : deviceStateList){ Long itemData = resultMap.get(item); if(Objects.isNull(itemData)){ resultMap.put(item,0L); } } return resultMap; } private Map countStateMapWithTenantId(String tenantId) { Map resultMap = new HashMap(); List finalDeptList = PredicateBuilder.queryCacheChildDeptIds(tenantId); List result = jpaQueryFactory.select(tbDeviceInfo.id.count(), tbDeviceInfo.state).from(tbDeviceInfo) // .leftJoin(tbProduct).on(tbProduct.productKey.eq(tbDeviceInfo.productKey)) .where(tbDeviceInfo.tenantId.eq(tenantId).and(tbDeviceInfo.createDept.in(finalDeptList))) .groupBy(tbDeviceInfo.state).fetch(); for (Tuple tuple : result) { resultMap.put(tuple.get(1, String.class), tuple.get(0, Long.class)); } Long noRegistResult = jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.state.eq("offline") .and(tbDeviceInfo.onlineTime.isNull().and(tbDeviceInfo.tenantId.eq(tenantId)).and(tbDeviceInfo.createDept.in(finalDeptList)))) // .leftJoin(tbProduct).on(tbProduct.productKey.eq(tbDeviceInfo.productKey)) // .where(tbProduct.tenantId.eq(tenantId)) .fetchOne(); resultMap.put("unactivated", noRegistResult); // Long offlineNum = resultMap.get("offline"); if (Objects.nonNull(offlineNum)) { resultMap.put("offline", offlineNum - noRegistResult); } return resultMap; } private Map countStateMapWithoutTenantId() { Map resultMap = new HashMap(); List result = jpaQueryFactory.select(tbDeviceInfo.id.count(), tbDeviceInfo.state).from(tbDeviceInfo).groupBy(tbDeviceInfo.state).fetch(); for (Tuple tuple : result) { resultMap.put(tuple.get(1, String.class), tuple.get(0, Long.class)); } Long noRegistResult = jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.state.eq("offline") .and(tbDeviceInfo.onlineTime.isNull())).fetchOne(); resultMap.put("unactivated", noRegistResult); // Long offlineNum = resultMap.get("offline"); if (Objects.nonNull(offlineNum)) { resultMap.put("offline", offlineNum - noRegistResult); } return resultMap; } @Override public Map countCategoryMap(String tenantId) { Map resultMap = new HashMap(); List finalDeptList = PredicateBuilder.queryCacheChildDeptIds(tenantId); List result = jpaQueryFactory.select(tbDeviceInfo.id.count(), tbDeviceInfo.productKey).from(tbDeviceInfo) .where(tbDeviceInfo.tenantId.eq(tenantId).and(tbDeviceInfo.createDept.in(finalDeptList))).groupBy(tbDeviceInfo.productKey).fetch(); for (Tuple tuple : result) { resultMap.put(tuple.get(1, String.class), tuple.get(0, Long.class)); } return resultMap; } @Override public Long countTodayAdd(String tenantId) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.HOUR, 0); calendar.set(Calendar.MILLISECOND, 0); List finalDeptList = PredicateBuilder.queryCacheChildDeptIds(tenantId); return jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.createAt.gt(calendar.getTime().getTime()) .and(tbDeviceInfo.tenantId.eq(tenantId)).and(tbDeviceInfo.createDept.in(finalDeptList))).fetchOne(); } @Override public Paging findByConditionsAndTenantId(String uid, String subUid, String productKey, String group, String state, String keyword, Integer page, Integer size, String tenantId,Long deptId) { if(StringUtils.isBlank(tenantId)){ return new Paging<>(0, Collections.emptyList()); } JPAQuery query = jpaQueryFactory.selectFrom(tbDeviceInfo); if (StringUtils.isNotBlank(uid)) { query.where(tbDeviceInfo.uid.eq(uid)); } 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 (StringUtils.isNotBlank(state)) { query.where(tbDeviceInfo.state.eq(state)); } if (StringUtils.isNotBlank(keyword)) { query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%") .or(tbDeviceInfo.deviceName.like("%" + keyword + "%"))); } // if (tenantId != null && !tenantId.equals("000000")) { // query.leftJoin(tbProduct).on(tbProduct.productKey.eq(tbDeviceInfo.productKey)).where(tbProduct.tenantId.eq(tenantId)); // } if (StringUtils.isNotBlank(tenantId)){ query.where(tbDeviceInfo.tenantId.eq(tenantId)); List finalDeptList = PredicateBuilder.queryCacheChildDeptsByDeptId(tenantId,deptId); if(CollectionUtil.isNotEmpty(finalDeptList)){ query.where(tbDeviceInfo.createDept.in(finalDeptList)); } } query.orderBy(tbDeviceInfo.createAt.desc()); query.offset((page - 1) * size).limit(size); List tbDeviceInfos = query.fetch(); long total = query.fetchCount(); List 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 Long countByTenantId(String tenantId) { // if (StringUtils.isNotBlank(tenantId) && tenantId.equals("000000")) { // return this.count(); // } else { if (StringUtils.isNotBlank(tenantId)) { List finalDeptList = PredicateBuilder.queryCacheChildDeptIds(tenantId); // if(CollectionUtil.isNotEmpty(finalDeptList)){ return jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.tenantId.eq(tenantId).and(tbDeviceInfo.createDept.in(finalDeptList)) ).fetchOne(); // }else{ // return jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.tenantId.eq(tenantId)).fetchOne(); // } } else { return 0L; // } } } }