SyncData.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. package com.zoniot.ccrc.scheduled;
  2. import cn.hutool.core.date.DateField;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.core.date.DateUtil;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.JSONObject;
  7. import com.zoniot.ccrc.commom.Constants;
  8. import com.zoniot.ccrc.commom.utils.HttpRequest;
  9. import com.zoniot.ccrc.commom.utils.RedisUtil;
  10. import com.zoniot.ccrc.commom.utils.SnowflakeIdWorker;
  11. import com.zoniot.ccrc.dao.CommunityMapper;
  12. import com.zoniot.ccrc.dao.MeterReadRecordMapper;
  13. import com.zoniot.ccrc.dao.MeterRecordMapper;
  14. import com.zoniot.ccrc.entity.*;
  15. import lombok.extern.slf4j.Slf4j;
  16. import org.apache.commons.lang3.StringUtils;
  17. import org.springframework.beans.factory.annotation.Autowired;
  18. import org.springframework.beans.factory.annotation.Value;
  19. import org.springframework.scheduling.annotation.Scheduled;
  20. import org.springframework.stereotype.Service;
  21. import javax.annotation.Resource;
  22. import java.io.IOException;
  23. import java.math.BigDecimal;
  24. import java.text.SimpleDateFormat;
  25. import java.time.LocalDateTime;
  26. import java.time.ZoneId;
  27. import java.time.format.DateTimeFormatter;
  28. import java.util.ArrayList;
  29. import java.util.Date;
  30. import java.util.List;
  31. @Slf4j
  32. @Service
  33. public class SyncData {
  34. @Resource
  35. SnowflakeIdWorker snowflakeIdWorker ;
  36. @Resource
  37. MeterReadRecordMapper meterReadRecordMapper;
  38. @Resource
  39. MeterRecordMapper meterRecordMapper;
  40. @Autowired
  41. RedisUtil redisUtil;
  42. @Value("${site_id}")
  43. private String siteId;
  44. @Value("${province_id}")
  45. private String provinceId;
  46. @Value("${city_id}")
  47. private String cityId;
  48. @Value("${region_id}")
  49. private String regionId;
  50. @Value("${geomap.apikey}")
  51. private String apikey;
  52. @Value("${geomap.api.url}")
  53. private String apiUrl;
  54. @Resource
  55. private CommunityMapper communityMapper;
  56. @Scheduled(cron = "0 0 20 * * ?")
  57. public void synchronousData(){
  58. syncCell();
  59. log.info("同步小区完毕");
  60. syncDevice();
  61. log.info("同步设备完毕");
  62. syncReading();
  63. log.info("同步设备读数完毕");
  64. synchronizeLatitudeAndLongitude();
  65. log.info("小区地理反编码完毕");
  66. }
  67. private void syncDevice(){
  68. meterRecordMapper.syncDevice(siteId,1);
  69. meterRecordMapper.deleteDevice();
  70. }
  71. private void syncCell(){
  72. meterRecordMapper.syncCell(siteId,provinceId,cityId,regionId);
  73. }
  74. private void syncReading(){
  75. int size=1000;
  76. int offset=0;
  77. SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMdd");
  78. int readDay=Integer.parseInt(simpleDateFormat.format(new Date()));
  79. while(true){
  80. List<WaterMeter> waterMeterList =meterRecordMapper.
  81. findWaterMeterListWithPage(offset, size);
  82. if(waterMeterList.isEmpty()){
  83. break;
  84. }
  85. offset=offset+size;
  86. generateReadingRecords(waterMeterList,readDay);
  87. }
  88. meterRecordMapper.updateDeviceStatus();
  89. }
  90. private String[] getInfoFromGaode(String name,String city){
  91. name=name.trim();
  92. String request = apiUrl+"?key="+apikey+"&address="+name+"&city="+city;
  93. String[] tts=null;
  94. try {
  95. String jsonContent = HttpRequest.doGet(request);
  96. JSONObject parse = (JSONObject)JSON.parse(jsonContent);
  97. int count = Integer.parseInt((String)parse.get("count"));
  98. if(count != 0) {
  99. JSONObject geocodes=parse.getJSONArray("geocodes").getJSONObject(0);
  100. String rtnContent =geocodes.get("location").toString();
  101. if(StringUtils.isNotBlank(rtnContent)) {
  102. tts=new String[3];
  103. String []latitudeAndLongitude= rtnContent.split(",");
  104. tts[0] =latitudeAndLongitude[0];
  105. tts[1] =latitudeAndLongitude[1];
  106. tts[2] =geocodes.getString("formatted_address");
  107. }
  108. }
  109. } catch (IOException e) {
  110. e.printStackTrace();
  111. }
  112. return tts;
  113. }
  114. private void synchronizeLatitudeAndLongitude(){
  115. meterRecordMapper.deleteCell();
  116. List<Community>communitys=meterRecordMapper.getCommunityIds();
  117. communitys.forEach(community -> {
  118. String[] infoFromGaode = getInfoFromGaode(community.getName(),community.getAddress());
  119. Community updateCommunity=new Community();
  120. updateCommunity.setId(community.getId());
  121. if(infoFromGaode!=null){
  122. updateCommunity.setAddress(infoFromGaode[2]);
  123. updateCommunity.setLongitude(Double.parseDouble(infoFromGaode[0]));
  124. updateCommunity.setLatitude(Double.parseDouble(infoFromGaode[1]));
  125. }
  126. updateCommunity.setSyncFlag(1);
  127. communityMapper.updateByPrimaryKeySelective(updateCommunity);
  128. });
  129. }
  130. public void generateReadingRecords(List<WaterMeter> waterMeterList,
  131. Integer readDay){
  132. log.info("begin batch create meter record , data size = {},readDay={}",waterMeterList.size(),readDay);
  133. int i = 0 ;
  134. if(compareMeterReadDay(readDay) < 0 ){
  135. log.warn("Not Support Passed ReadDay = {}",readDay);
  136. }
  137. else{
  138. List<MeterReadRecord> meterReadRecordList = new ArrayList<>();
  139. for (WaterMeter waterMeter : waterMeterList){
  140. MeterReadRecord meterReadRecord = buildUnReadRecord(waterMeter, readDay);
  141. if(meterReadRecord != null){
  142. meterReadRecordList.add(meterReadRecord);
  143. updateReadData(waterMeter);
  144. }
  145. if (meterReadRecordList.size() == Constants.BATCH_SIZE){
  146. // 按批次提交
  147. int insert = meterReadRecordMapper.batchInsert(meterReadRecordList);
  148. i = i+insert ;
  149. meterReadRecordList.clear();
  150. }
  151. }
  152. if(!meterReadRecordList.isEmpty()){
  153. int insert = meterReadRecordMapper.batchInsert(meterReadRecordList);
  154. i = i+insert ;
  155. meterReadRecordList.clear();
  156. }
  157. }
  158. log.info("end batch create meter record , readDay={} ,result size = {}",readDay,i);
  159. }
  160. public void updateReadData(WaterMeter waterMeter){
  161. if(waterMeter.getDeviceTypeId()==1){
  162. MeterReadRecord meterReadRecord=new MeterReadRecord();
  163. meterReadRecord.setDeviceId(waterMeter.getDeviceId());
  164. setMeterRead(waterMeter.getRegistNo(),meterReadRecord);
  165. DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
  166. LocalDateTime endDateTime = LocalDateTime.now().plusDays(-1);
  167. Integer readDay = Integer.valueOf(endDateTime.format(df));
  168. meterReadRecord.setReadDate(readDay);
  169. meterRecordMapper.updateReadData(meterReadRecord);
  170. }
  171. }
  172. /**
  173. * 将抄表日期与当期日期进行比较
  174. * 若抄表日期大于当前日期返回值>0
  175. * 若抄表日期等于当前日期返回值=0
  176. * 若抄表日期早于当前日期返回值<0
  177. * @param readDay
  178. * @return
  179. */
  180. protected int compareMeterReadDay(int readDay){
  181. Integer today = Integer.parseInt(DateUtil.format(DateUtil.date(), Constants.DEFAULT_METER_READ_DATE_FORMAT));
  182. return readDay-today;
  183. }
  184. /**
  185. * 构造未抄记录
  186. * @param waterMeter
  187. * @param readDay
  188. * @return
  189. */
  190. protected MeterReadRecord buildUnReadRecord(WaterMeter waterMeter , Integer readDay){
  191. MeterReadRecord meterReadRecord = new MeterReadRecord() ;
  192. Integer type=waterMeter.getDeviceTypeId();
  193. meterReadRecord.setSiteId(waterMeter.getSiteId());
  194. meterReadRecord.setSysId(waterMeter.getSysId());
  195. meterReadRecord.setCommunity(waterMeter.getCommunity());
  196. meterReadRecord.setMeterFileNo(waterMeter.getMeterFileNo());
  197. meterReadRecord.setMeterNo(waterMeter.getMeterNo());
  198. meterReadRecord.setDateCreate(LocalDateTime.now());
  199. meterReadRecord.setDeviceId(waterMeter.getDeviceId());
  200. meterReadRecord.setDeviceNo(waterMeter.getDeviceNo());
  201. meterReadRecord.setDeviceTypeId(waterMeter.getDeviceTypeId());
  202. meterReadRecord.setId(snowflakeIdWorker.nextId());
  203. meterReadRecord.setLastCost(new BigDecimal(0));
  204. meterReadRecord.setLocation(waterMeter.getLocation());
  205. meterReadRecord.setCreateBy(Constants.SYS_FLAG);
  206. meterReadRecord.setStatus(1);
  207. meterReadRecord.setReadDate(readDay);
  208. meterReadRecord.setCity(Integer.parseInt(cityId));
  209. meterReadRecord.setReadStatus(Constants.UN_READ);
  210. meterReadRecord.setRegion(Integer.parseInt(regionId));
  211. meterReadRecord.setProvince(Integer.parseInt(provinceId));
  212. meterReadRecord.setLastValid(getMeterLastValid(waterMeter,readDay));
  213. if(type==2){
  214. setMeterRead(waterMeter.getRegistNo(),meterReadRecord);
  215. meterReadRecord.setReadStatus(Constants.READ);
  216. }
  217. return meterReadRecord ;
  218. }
  219. private LocalDateTime changeDateType(Date date){
  220. LocalDateTime localDateTime=null;
  221. if(date!=null){
  222. localDateTime= date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
  223. }
  224. return localDateTime;
  225. }
  226. private void setMeterRead(String registNo,MeterReadRecord meterReadRecord){
  227. MeterRecord meterRecord = meterRecordMapper.get(registNo);
  228. if(meterRecord!=null){
  229. String reading=meterRecord.getMeterReading()+"";
  230. meterReadRecord.setLastValid(reading);
  231. meterReadRecord.setReadTime(changeDateType(meterRecord.getReadingTime()));
  232. meterReadRecord.setReadData(reading);
  233. BigDecimal todayCost = BigDecimal.valueOf(calculateTodayCost(reading,
  234. new Double(meterReadRecord.getLastValid())));
  235. todayCost = todayCost.setScale(3,BigDecimal.ROUND_HALF_UP);
  236. meterReadRecord.setLastCost(todayCost);
  237. meterReadRecord.setValveState(meterRecord.getValveStatus());
  238. meterReadRecord.setMeterStatusInfo(meterRecord.getMeterStatusInfo());
  239. meterReadRecord.setReadStatus(meterRecord.getMeterStatus()+"");
  240. setMeterLastDataToCache(meterReadRecord.getDeviceId(),reading);
  241. }
  242. }
  243. private Double calculateTodayCost(String currentReading,Double lastValid){
  244. Double currentValid = new Double(currentReading);
  245. return currentValid-lastValid;
  246. }
  247. /**
  248. * 获取水表最后止度,先从缓存中获取止度,缓存无数据则从数据库中获取
  249. * @param waterMeter
  250. * @param readDate
  251. * @return
  252. */
  253. protected String getMeterLastValid(WaterMeter waterMeter,Integer readDate){
  254. String lastValid = "0" ;
  255. String lastValidFromCache = getMeterLastValidFromCache(waterMeter);
  256. if(StringUtils.isBlank(lastValidFromCache)){
  257. String lastValidFromDB = getMeterLastValidFromDB(waterMeter, readDate);
  258. if(StringUtils.isNotBlank(lastValidFromDB)){
  259. lastValid = lastValidFromDB;
  260. }
  261. }
  262. else{
  263. lastValid = lastValidFromCache ;
  264. }
  265. return lastValid;
  266. }
  267. /**
  268. * 从数据库中获取最后止度,默认为前一天的抄表最后止度
  269. * @param waterMeter
  270. * @param readDate
  271. * @return
  272. */
  273. protected String getMeterLastValidFromDB(WaterMeter waterMeter,Integer readDate){
  274. // 默认水表止度
  275. String lastValid = "" ;
  276. // 计算输入日期的前一日
  277. DateTime inputDate = DateUtil.parse(String.valueOf(readDate), Constants.DEFAULT_METER_READ_DATE_FORMAT);
  278. DateTime previousDate = DateUtil.offset(inputDate, DateField.DAY_OF_MONTH, -1);
  279. int previousDay = Integer.parseInt(DateUtil.format(previousDate.toJdkDate(), Constants.DEFAULT_METER_READ_DATE_FORMAT));
  280. // 查询前一日抄表记录
  281. MeterReadRecord previousRecord= findRecordByMeterIdAndReadDate(waterMeter, previousDay);
  282. if(previousRecord != null){
  283. lastValid = previousRecord.getLastValid();
  284. }
  285. return lastValid ;
  286. }
  287. /**
  288. * 从缓存中获取水表的最后止度
  289. * @param waterMeter
  290. * @return
  291. */
  292. protected String getMeterLastValidFromCache(WaterMeter waterMeter){
  293. // 默认水表止度
  294. String lastValid = "" ;
  295. String meterLastData = getMeterLastDataFromCache(waterMeter.getDeviceId());
  296. if(StringUtils.isNotBlank(meterLastData)){
  297. lastValid=meterLastData;
  298. }
  299. return lastValid ;
  300. }
  301. /**
  302. * 从缓存中获取水表最后上报数据
  303. * @param deviceId
  304. * @return
  305. */
  306. protected String getMeterLastDataFromCache(Long deviceId){
  307. return redisUtil.get(Constants.PREFIX_CACHE_FLAG+deviceId);
  308. }
  309. public MeterReadRecord findRecordByMeterIdAndReadDate(WaterMeter waterMeter, Integer readDate) {
  310. return meterReadRecordMapper.findRecordByReadDayAndDeviceId(waterMeter.getDeviceId(), readDate);
  311. }
  312. protected void setMeterLastDataToCache(Long deviceId ,String measuringData){
  313. redisUtil.set(Constants.PREFIX_CACHE_FLAG+deviceId,measuringData);
  314. }
  315. }