DeviceInfoDataImpl.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. package cc.iotkit.data.service;
  2. import cc.iotkit.common.api.PageRequest;
  3. import cc.iotkit.common.api.Paging;
  4. import cc.iotkit.common.utils.MapstructUtils;
  5. import cc.iotkit.common.utils.ReflectUtil;
  6. import cc.iotkit.data.dao.*;
  7. import cc.iotkit.data.manager.ICategoryData;
  8. import cc.iotkit.data.manager.IDeviceInfoData;
  9. import cc.iotkit.data.manager.IProductData;
  10. import cc.iotkit.data.model.*;
  11. import cc.iotkit.data.util.PageBuilder;
  12. import cc.iotkit.model.device.DeviceInfo;
  13. import cc.iotkit.model.device.message.DevicePropertyCache;
  14. import cc.iotkit.model.product.Category;
  15. import cc.iotkit.model.product.Product;
  16. import cc.iotkit.model.stats.DataItem;
  17. import com.querydsl.core.Tuple;
  18. import com.querydsl.core.types.Projections;
  19. import com.querydsl.jpa.impl.JPAQuery;
  20. import com.querydsl.jpa.impl.JPAQueryFactory;
  21. import lombok.RequiredArgsConstructor;
  22. import org.apache.commons.lang3.StringUtils;
  23. import org.springframework.beans.factory.annotation.Qualifier;
  24. import org.springframework.context.annotation.Primary;
  25. import org.springframework.data.domain.Page;
  26. import org.springframework.data.jpa.repository.JpaRepository;
  27. import org.springframework.stereotype.Service;
  28. import org.springframework.transaction.annotation.Transactional;
  29. import java.util.*;
  30. import java.util.stream.Collectors;
  31. import static cc.iotkit.data.model.QTbDeviceGroupMapping.tbDeviceGroupMapping;
  32. import static cc.iotkit.data.model.QTbDeviceInfo.tbDeviceInfo;
  33. import static cc.iotkit.data.model.QTbDeviceSubUser.tbDeviceSubUser;
  34. import static cc.iotkit.data.model.QTbProduct.tbProduct;
  35. @Primary
  36. @Service
  37. @RequiredArgsConstructor
  38. public class DeviceInfoDataImpl implements IDeviceInfoData, IJPACommData<DeviceInfo, String> {
  39. private final DeviceInfoRepository deviceInfoRepository;
  40. private final DeviceSubUserRepository deviceSubUserRepository;
  41. private final DeviceGroupMappingRepository deviceGroupMappingRepository;
  42. private final DeviceGroupRepository deviceGroupRepository;
  43. private final DeviceTagRepository deviceTagRepository;
  44. @Qualifier("productDataCache")
  45. private final IProductData productData;
  46. @Qualifier("categoryDataCache")
  47. private final ICategoryData categoryData;
  48. private final JPAQueryFactory jpaQueryFactory;
  49. @Override
  50. public JpaRepository getBaseRepository() {
  51. return deviceInfoRepository;
  52. }
  53. @Override
  54. public Class getJpaRepositoryClass() {
  55. return TbDeviceInfo.class;
  56. }
  57. @Override
  58. public Class getTClass() {
  59. return DeviceInfo.class;
  60. }
  61. @Override
  62. public void saveProperties(String deviceId, Map<String, DevicePropertyCache> properties) {
  63. }
  64. @Override
  65. public Map<String, DevicePropertyCache> getProperties(String deviceId) {
  66. return new HashMap<>();
  67. }
  68. @Override
  69. public DeviceInfo findByDeviceId(String deviceId) {
  70. TbDeviceInfo tbDeviceInfo = deviceInfoRepository.findByDeviceId(deviceId);
  71. DeviceInfo dto = MapstructUtils.convert(tbDeviceInfo, DeviceInfo.class);
  72. fillDeviceInfo(deviceId, tbDeviceInfo, dto);
  73. return dto;
  74. }
  75. /**
  76. * 填充设备其它信息
  77. */
  78. private void fillDeviceInfo(String deviceId, TbDeviceInfo vo, DeviceInfo dto) {
  79. if (vo == null || dto == null) {
  80. return;
  81. }
  82. //取子关联用户
  83. dto.setSubUid(deviceSubUserRepository.findByDeviceId(deviceId).stream()
  84. .map(TbDeviceSubUser::getUid).collect(Collectors.toList()));
  85. //取设备所属分组
  86. List<TbDeviceGroupMapping> groupMappings = deviceGroupMappingRepository.findByDeviceId(deviceId);
  87. Map<String, DeviceInfo.Group> groups = new HashMap<>();
  88. for (TbDeviceGroupMapping mapping : groupMappings) {
  89. TbDeviceGroup deviceGroup = deviceGroupRepository.findById(mapping.getGroupId()).orElse(null);
  90. if (deviceGroup == null) {
  91. continue;
  92. }
  93. groups.put(deviceGroup.getId(), new DeviceInfo.Group(deviceGroup.getId(), deviceGroup.getName()));
  94. }
  95. dto.setGroup(groups);
  96. //取设备标签
  97. List<TbDeviceTag> deviceTags = deviceTagRepository.findByDeviceId(deviceId);
  98. Map<String, DeviceInfo.Tag> tagMap = new HashMap<>();
  99. for (TbDeviceTag tag : deviceTags) {
  100. tagMap.put(tag.getCode(), new DeviceInfo.Tag(tag.getCode(), tag.getName(), tag.getValue()));
  101. }
  102. dto.setTag(tagMap);
  103. //将设备状态从vo转为dto的
  104. parseStateToDto(vo, dto);
  105. }
  106. /**
  107. * 将设备状态从vo转为dto的
  108. */
  109. private void parseStateToDto(TbDeviceInfo vo, DeviceInfo dto) {
  110. dto.setState(new DeviceInfo.State("online".equals(vo.getState()),
  111. vo.getOnlineTime(), vo.getOfflineTime()));
  112. dto.setLocate(new DeviceInfo.Locate(vo.getLongitude(), vo.getLatitude()));
  113. }
  114. /**
  115. * 将设备状态从dto转vo
  116. */
  117. private void parseStateToVo(DeviceInfo dto, TbDeviceInfo vo) {
  118. DeviceInfo.State state = dto.getState();
  119. vo.setState(state.isOnline() ? "online" : "offline");
  120. vo.setOfflineTime(state.getOfflineTime());
  121. vo.setOnlineTime(state.getOnlineTime());
  122. DeviceInfo.Locate locate = dto.getLocate();
  123. vo.setLongitude(locate.getLongitude());
  124. vo.setLatitude(locate.getLatitude());
  125. }
  126. /**
  127. * 将数据库中查出来的vo转为dto
  128. */
  129. private DeviceInfo parseVoToDto(TbDeviceInfo vo) {
  130. if (vo == null) {
  131. return null;
  132. }
  133. DeviceInfo dto = MapstructUtils.convert(vo, DeviceInfo.class);
  134. fillDeviceInfo(vo.getDeviceId(), vo, dto);
  135. return dto;
  136. }
  137. /**
  138. * 将数据库中查出来的vo列表转为dto列表
  139. */
  140. private List<DeviceInfo> parseVoToDto(List<TbDeviceInfo> vos) {
  141. return vos.stream().map(d -> {
  142. DeviceInfo dto = MapstructUtils.convert(d, DeviceInfo.class);
  143. fillDeviceInfo(d.getDeviceId(), d, dto);
  144. return dto;
  145. }).collect(Collectors.toList());
  146. }
  147. @Override
  148. public DeviceInfo findByDeviceName(String deviceName) {
  149. return parseVoToDto(deviceInfoRepository.findByDeviceName(deviceName));
  150. }
  151. @Override
  152. public List<DeviceInfo> findByParentId(String parentId) {
  153. return parseVoToDto(deviceInfoRepository.findByParentId(parentId));
  154. }
  155. @Override
  156. public List<String> findSubDeviceIds(String parentId) {
  157. return jpaQueryFactory.select(tbDeviceInfo.deviceId).from(tbDeviceInfo)
  158. .where(tbDeviceInfo.parentId.eq(parentId)).fetch();
  159. }
  160. @Override
  161. public List<DeviceInfo> findByProductNodeType(String uid) {
  162. List<TbDeviceInfo> devices = jpaQueryFactory.select(tbDeviceInfo).from(tbDeviceInfo)
  163. .join(tbProduct).on(tbProduct.nodeType.eq(0).and(tbDeviceInfo.productKey.eq(tbProduct.productKey))).fetch();
  164. return MapstructUtils.convert(devices, DeviceInfo.class);
  165. }
  166. @Override
  167. public boolean existByProductKey(String productKey) {
  168. return Optional.ofNullable(jpaQueryFactory.selectOne().from(tbDeviceInfo).where(tbDeviceInfo.productKey.eq(productKey)).fetchOne()).orElse(0) > 0;
  169. }
  170. @Override
  171. public Paging<DeviceInfo> findByConditions(String uid, String subUid,
  172. String productKey, String groupId,
  173. String state, String keyword,
  174. int page, int size) {
  175. JPAQuery<TbDeviceInfo> query = jpaQueryFactory.selectFrom(tbDeviceInfo);
  176. if (StringUtils.isNotBlank(uid)) {
  177. query.where(tbDeviceInfo.uid.eq(uid));
  178. }
  179. if (StringUtils.isNotBlank(subUid)) {
  180. query.join(tbDeviceSubUser).on(tbDeviceSubUser.deviceId.eq(tbDeviceInfo.deviceId));
  181. query.where(tbDeviceSubUser.uid.eq(subUid));
  182. }
  183. if (StringUtils.isNotBlank(productKey)) {
  184. query.where(tbDeviceInfo.productKey.eq(productKey));
  185. }
  186. if (StringUtils.isNotBlank(state)) {
  187. query.where(tbDeviceInfo.state.eq(state));
  188. }
  189. if (StringUtils.isNotBlank(keyword)) {
  190. query.where(tbDeviceInfo.deviceId.like("%" + keyword + "%")
  191. .or(tbDeviceInfo.deviceName.like("%" + keyword + "%")));
  192. }
  193. query.orderBy(tbDeviceInfo.createAt.desc());
  194. query.offset((page - 1) * size).limit(size);
  195. List<TbDeviceInfo> tbDeviceInfos = query.fetch();
  196. long total = query.fetchCount();
  197. List<DeviceInfo> deviceInfos = new ArrayList<>(tbDeviceInfos.size());
  198. for (TbDeviceInfo tbDeviceInfo : tbDeviceInfos) {
  199. DeviceInfo deviceInfo = MapstructUtils.convert(tbDeviceInfo, DeviceInfo.class);
  200. fillDeviceInfo(tbDeviceInfo.getDeviceId(), tbDeviceInfo, deviceInfo);
  201. deviceInfos.add(deviceInfo);
  202. }
  203. return new Paging<>(total, deviceInfos);
  204. }
  205. @Override
  206. public void updateTag(String deviceId, DeviceInfo.Tag tag) {
  207. TbDeviceTag deviceTag = deviceTagRepository.findByDeviceIdAndCode(deviceId, tag.getId());
  208. if (deviceTag != null) {
  209. deviceTag.setName(tag.getName());
  210. deviceTag.setValue(tag.getValue());
  211. deviceTagRepository.save(deviceTag);
  212. } else {
  213. deviceTagRepository.save(
  214. TbDeviceTag.builder()
  215. .id(UUID.randomUUID().toString())
  216. .code(tag.getId())
  217. .deviceId(deviceId)
  218. .name(tag.getName())
  219. .value(tag.getValue())
  220. .build()
  221. );
  222. }
  223. }
  224. @Override
  225. public List<DataItem> getDeviceStatsByCategory(String uid) {
  226. //先按产品统计设备数量
  227. JPAQuery<DataItem> query = jpaQueryFactory.select(Projections.bean(DataItem.class,
  228. tbDeviceInfo.productKey,
  229. tbDeviceInfo.count()))
  230. .from(tbDeviceInfo)
  231. .groupBy(tbDeviceInfo.productKey);
  232. if (StringUtils.isNotBlank(uid)) {
  233. query.where(tbDeviceInfo.uid.eq(uid));
  234. }
  235. List<DataItem> stats = new ArrayList<>();
  236. List<DataItem> rst = query.fetch();
  237. for (DataItem item : rst) {
  238. //找到产品对应的品类取出品类名
  239. Product product = productData.findByProductKey(item.getName());
  240. String cateId = product.getCategory();
  241. Category category = categoryData.findById(cateId);
  242. if (category == null) {
  243. continue;
  244. }
  245. //将数据替换成按品类的数据
  246. item.setName(category.getName());
  247. }
  248. //按品类分组求合
  249. rst.stream().collect(Collectors.groupingBy(DataItem::getName,
  250. Collectors.summarizingLong(item -> (long) item.getValue())))
  251. .forEach((key, sum) -> stats.add(new DataItem(key, sum.getSum())));
  252. return stats;
  253. }
  254. @Override
  255. public long countByGroupId(String groupId) {
  256. return deviceGroupMappingRepository.countByGroupId(groupId);
  257. }
  258. @Override
  259. @Transactional
  260. public void addToGroup(String deviceId, DeviceInfo.Group group) {
  261. String groupId = UUID.randomUUID().toString();
  262. deviceGroupMappingRepository.save(new TbDeviceGroupMapping(groupId, deviceId, group.getId()));
  263. //更新设备数量
  264. updateGroupDeviceCount(groupId);
  265. }
  266. private void updateGroupDeviceCount(String groupId) {
  267. //更新设备数量
  268. TbDeviceGroup deviceGroup = deviceGroupRepository.findById(groupId).orElse(null);
  269. if (deviceGroup != null) {
  270. deviceGroup.setDeviceQty((int) countByGroupId(groupId));
  271. deviceGroupRepository.save(deviceGroup);
  272. }
  273. }
  274. @Override
  275. public void updateGroup(String groupId, DeviceInfo.Group group) {
  276. //更新设备信息中的分组信息,关系数据库中不需要实现
  277. }
  278. @Override
  279. @Transactional
  280. public void removeGroup(String deviceId, String groupId) {
  281. jpaQueryFactory.delete(tbDeviceGroupMapping)
  282. .where(tbDeviceGroupMapping.deviceId.eq(deviceId)
  283. .and(tbDeviceGroupMapping.groupId.eq(groupId)))
  284. .execute();
  285. //更新设备数量
  286. updateGroupDeviceCount(groupId);
  287. }
  288. @Override
  289. @Transactional
  290. public void removeGroup(String groupId) {
  291. jpaQueryFactory.delete(tbDeviceGroupMapping)
  292. .where(tbDeviceGroupMapping.groupId.eq(groupId))
  293. .execute();
  294. //更新设备数量
  295. updateGroupDeviceCount(groupId);
  296. }
  297. @Override
  298. public List<DeviceInfo> findByUid(String uid) {
  299. return new ArrayList<>();
  300. }
  301. @Override
  302. public Paging<DeviceInfo> findByUid(String uid, int page, int size) {
  303. return new Paging<>();
  304. }
  305. @Override
  306. public long countByUid(String uid) {
  307. return 0;
  308. }
  309. @Override
  310. public DeviceInfo findById(String s) {
  311. return MapstructUtils.convert(
  312. deviceInfoRepository.findById(s).orElse(null), DeviceInfo.class);
  313. }
  314. @Override
  315. public List<DeviceInfo> findByIds(Collection<String> ids) {
  316. return MapstructUtils.convert(deviceInfoRepository.findAllById(ids),DeviceInfo.class);
  317. }
  318. @Override
  319. @Transactional
  320. public DeviceInfo save(DeviceInfo data) {
  321. TbDeviceInfo vo = deviceInfoRepository.findByDeviceId(data.getDeviceId());
  322. if (StringUtils.isBlank(data.getId())) {
  323. data.setId(UUID.randomUUID().toString());
  324. }
  325. if (vo == null) {
  326. vo = new TbDeviceInfo();
  327. }
  328. ReflectUtil.copyNoNulls(data, vo);
  329. //状态转换
  330. parseStateToVo(data, vo);
  331. //保存设备信息
  332. deviceInfoRepository.save(vo);
  333. //设备分组转换
  334. Map<String, DeviceInfo.Group> groupMap = data.getGroup();
  335. groupMap.forEach((id, group) -> {
  336. TbDeviceGroupMapping mapping = deviceGroupMappingRepository.findByDeviceIdAndGroupId(data.getDeviceId(), id);
  337. if (mapping == null) {
  338. //保存设备分组与设备对应关系
  339. deviceGroupMappingRepository.save(new TbDeviceGroupMapping(
  340. UUID.randomUUID().toString(),
  341. data.getDeviceId(),
  342. id
  343. ));
  344. }
  345. });
  346. return data;
  347. }
  348. @Override
  349. public void batchSave(List<DeviceInfo> data) {
  350. }
  351. @Override
  352. public void deleteById(String s) {
  353. deviceInfoRepository.deleteById(s);
  354. }
  355. @Override
  356. public void deleteByIds(Collection<String> ids) {
  357. deviceInfoRepository.deleteAllById(ids);
  358. }
  359. @Override
  360. public long count() {
  361. return deviceInfoRepository.count();
  362. }
  363. @Override
  364. public List<DeviceInfo> findAll() {
  365. return new ArrayList<>();
  366. }
  367. @Override
  368. public Paging<DeviceInfo> findAll(PageRequest<DeviceInfo> pageRequest) {
  369. Page<TbDeviceInfo> ret = deviceInfoRepository.findAll(PageBuilder.toPageable(pageRequest));
  370. return new Paging<>(ret.getTotalElements(), MapstructUtils.convert(ret.getContent(), DeviceInfo.class));
  371. }
  372. @Override
  373. public List<DeviceInfo> findAllByCondition(DeviceInfo data) {
  374. return Collections.emptyList();
  375. }
  376. @Override
  377. public DeviceInfo findOneByCondition(DeviceInfo data) {
  378. return null;
  379. }
  380. @Override
  381. public Map countStateMap() {
  382. Map<String,Long> resultMap = new HashMap();
  383. List<Tuple> result = jpaQueryFactory.select(tbDeviceInfo.id.count(),tbDeviceInfo.state).from(tbDeviceInfo).groupBy(tbDeviceInfo.state).fetch();
  384. for(Tuple tuple: result){ resultMap.put(tuple.get(1,String.class),tuple.get(0,Long.class)); }
  385. Long noRegistResult = jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.state.eq("offline")
  386. .and(tbDeviceInfo.onlineTime.isNull())).fetchOne();
  387. resultMap.put("unactivated",noRegistResult);
  388. //
  389. Long offlineNum = resultMap.get("offline");
  390. if(Objects.nonNull(offlineNum)){
  391. resultMap.put("offline",offlineNum-noRegistResult);
  392. }
  393. return resultMap;
  394. }
  395. @Override
  396. public Map countCategoryMap() {
  397. Map<String,Long> resultMap = new HashMap();
  398. List<Tuple> result = jpaQueryFactory.select(tbDeviceInfo.id.count(),tbDeviceInfo.productKey).from(tbDeviceInfo).groupBy(tbDeviceInfo.productKey).fetch();
  399. for(Tuple tuple: result){ resultMap.put(tuple.get(1,String.class),tuple.get(0,Long.class)); }
  400. return resultMap;
  401. }
  402. @Override
  403. public Long countTodayAdd() {
  404. Calendar calendar = Calendar.getInstance();
  405. calendar.set(Calendar.HOUR_OF_DAY,0);
  406. calendar.set(Calendar.MINUTE,0);
  407. calendar.set(Calendar.HOUR,0);
  408. calendar.set(Calendar.MILLISECOND,0);
  409. return jpaQueryFactory.select(tbDeviceInfo.id.count()).from(tbDeviceInfo).where(tbDeviceInfo.createAt.gt(calendar.getTime().getTime())).fetchOne();
  410. }
  411. }