package com.ruoyi.http.service.impl;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.ruoyi.common.utils.http.HttpUtils;
|
import com.ruoyi.http.config.TqdianbiaoConfig;
|
import com.ruoyi.http.mapper.TqdianbiaoEleRecordMapper;
|
import com.ruoyi.http.mapper.TqdianbiaoMeterMapper;
|
import com.ruoyi.http.pojo.TqdianbiaoEleRecord;
|
import com.ruoyi.http.pojo.TqdianbiaoMeter;
|
import com.ruoyi.http.service.TqdianbiaoEleSyncService;
|
import com.ruoyi.http.service.TqdianbiaoSyncLogService;
|
import com.ruoyi.http.util.StatisticEleParseUtil;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.StringUtils;
|
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.List;
|
|
@Service
|
@Slf4j
|
@RequiredArgsConstructor
|
public class TqdianbiaoEleSyncServiceImpl implements TqdianbiaoEleSyncService {
|
|
private static final DateTimeFormatter HOUR_FMT = DateTimeFormatter.ofPattern("yyyyMMddHH");
|
private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
|
private static final DateTimeFormatter MONTH_FMT = DateTimeFormatter.ofPattern("yyyyMM");
|
private static final DateTimeFormatter YEAR_FMT = DateTimeFormatter.ofPattern("yyyy");
|
|
private final TqdianbiaoConfig config;
|
private final TqdianbiaoEleRecordMapper eleRecordMapper;
|
private final TqdianbiaoMeterMapper meterMapper;
|
private final TqdianbiaoSyncLogService syncLogService;
|
|
@Override
|
public int syncHourData() {
|
int window = config.getSync().getHourWindow() != null ? config.getSync().getHourWindow() : 1;
|
if (window < 1) {
|
window = 1;
|
}
|
// 结束于上一完整小时,不包含当前未结束的小时
|
LocalDateTime currentHourStart = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
|
LocalDateTime end = currentHourStart.minusHours(1);
|
LocalDateTime start = end.minusHours(window - 1L);
|
String startTime = start.format(HOUR_FMT);
|
String endTime = end.format(HOUR_FMT);
|
return syncDimension("hour", startTime, endTime);
|
}
|
|
@Override
|
public int syncLast3DaysHourData() {
|
LocalDateTime start = LocalDate.now().minusDays(3).atStartOfDay();
|
LocalDateTime end = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
|
return syncHourRangeInChunks(start, end);
|
}
|
|
/** 按最多 24 小时一段分批拉取(平台接口限制) */
|
private int syncHourRangeInChunks(LocalDateTime start, LocalDateTime end) {
|
int total = 0;
|
LocalDateTime windowStart = start;
|
while (!windowStart.isAfter(end)) {
|
LocalDateTime windowEnd = windowStart.plusHours(23);
|
if (windowEnd.isAfter(end)) {
|
windowEnd = end;
|
}
|
total += syncDimension("hour", windowStart.format(HOUR_FMT), windowEnd.format(HOUR_FMT));
|
windowStart = windowEnd.plusHours(1);
|
}
|
return total;
|
}
|
|
@Override
|
public int syncDayData() {
|
LocalDate yesterday = LocalDate.now().minusDays(1);
|
String day = yesterday.format(DAY_FMT);
|
return syncDimension("day", day, day);
|
}
|
|
@Override
|
public int syncMonthData() {
|
LocalDate now = LocalDate.now();
|
String month = now.format(MONTH_FMT);
|
return syncDimension("month", month, month);
|
}
|
|
@Override
|
public int syncYearData() {
|
LocalDate now = LocalDate.now();
|
String year = now.format(YEAR_FMT);
|
return syncDimension("year", year, year);
|
}
|
|
private int syncDimension(String dimension, String startTime, String endTime) {
|
return syncDimension(dimension, startTime, endTime, config.getIgnoreRadio());
|
}
|
|
private int syncDimension(String dimension, String startTime, String endTime, int ignoreRadio) {
|
try {
|
String url = config.getBaseUrl() + "/Api/StatisticEle/" + dimension;
|
String param = String.format(
|
"auth=%s&start_time=%s&end_time=%s&ignore_radio=%d",
|
config.getAuth(), startTime, endTime, ignoreRadio
|
);
|
log.info("同步电量数据: {} {}-{} ignore_radio={}", dimension, startTime, endTime, ignoreRadio);
|
String raw = HttpUtils.sendGet(url, param);
|
List<TqdianbiaoEleRecord> records = StatisticEleParseUtil.parseToEntities(raw, dimension);
|
enrichMeterInfo(records);
|
int count = upsertRecords(records);
|
syncLogService.logSuccess(dimension, startTime, endTime, count);
|
return count;
|
} catch (Exception e) {
|
log.error("电量同步失败 dimension={} {}-{}", dimension, startTime, endTime, e);
|
syncLogService.logFailure(dimension, startTime, endTime, e.getMessage());
|
throw e;
|
}
|
}
|
|
private void enrichMeterInfo(List<TqdianbiaoEleRecord> records) {
|
for (TqdianbiaoEleRecord record : records) {
|
if (record.getMeterId() == null) {
|
continue;
|
}
|
TqdianbiaoMeter meter = meterMapper.selectOne(
|
Wrappers.<TqdianbiaoMeter>lambdaQuery()
|
.eq(TqdianbiaoMeter::getMeterId, record.getMeterId())
|
.last("LIMIT 1"));
|
if (meter != null && StringUtils.hasText(meter.getMeterName())) {
|
record.setMeterName(meter.getMeterName());
|
}
|
}
|
}
|
|
private int upsertRecords(List<TqdianbiaoEleRecord> records) {
|
int count = 0;
|
for (TqdianbiaoEleRecord record : records) {
|
TqdianbiaoEleRecord existing = eleRecordMapper.selectOne(
|
Wrappers.<TqdianbiaoEleRecord>lambdaQuery()
|
.eq(TqdianbiaoEleRecord::getMeterId, record.getMeterId())
|
.eq(TqdianbiaoEleRecord::getDimension, record.getDimension())
|
.eq(TqdianbiaoEleRecord::getTimeKey, record.getTimeKey())
|
.last("LIMIT 1"));
|
if (existing == null) {
|
eleRecordMapper.insert(record);
|
} else {
|
record.setId(existing.getId());
|
eleRecordMapper.updateById(record);
|
}
|
count++;
|
}
|
return count;
|
}
|
}
|