package com.topsail.influxdb.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.influxdb.client.DeleteApi; import com.influxdb.client.InfluxDBClient; import com.influxdb.client.InfluxDBClientFactory; import com.influxdb.client.WriteApi; import com.influxdb.client.domain.WritePrecision; import com.influxdb.query.FluxRecord; import com.influxdb.query.FluxTable; import com.topsail.influxdb.entity.DeviceBelongInfo; import com.topsail.influxdb.entity.DeviceDataInfluxData; import com.topsail.influxdb.entity.DeviceHistoryData; import com.topsail.influxdb.entity.SyncDataFlag; import com.topsail.influxdb.mapper.DeviceInfoMapper; import com.topsail.influxdb.pojo.History; import com.topsail.influxdb.rabbitmq.service.AmqpService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.*; @Service public class DeviceDataService { public static final Logger LOG = LoggerFactory.getLogger(DeviceDataService.class); // InfluxDB基础配置 private static final String DEVICEDATA_BUCKET_NAME = "iot"; @Value("${shengdilan.influxdb.token}") public String token; @Value("${shengdilan.influxdb.url}") public String url; @Value("${shengdilan.influxdb.org}") private String org; @Value("${shengdilan.influxdb.oldtoken}") public String oldtoken; @Value("${shengdilan.influxdb.oldurl}") public String oldurl; @Value("${shengdilan.influxdb.oldorg}") private String oldorg; @Resource DeviceInfoMapper deviceInfoMapper; @Autowired AmqpService amqpService; /** * 根据设备号查询设备历史数据 * * @param uid * @param pageNo * @param pageSize * @param startTime * @param endTime * @param imei * @return */ public List getDeviceHistoryData(String uid, Integer pageNo, Integer pageSize, String startTime, String endTime, String imei) { InfluxDBClient client = InfluxDBClientFactory.create(url, token.toCharArray(), org); StringBuffer query = new StringBuffer(); query.append("from(bucket: \"iot\") "); if (startTime != null && endTime != null) { SimpleDateFormat oldFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); newFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//时区转换 String start = null; try { start = newFormat.format(oldFormat.parse(startTime)); String stop = newFormat.format(oldFormat.parse(endTime)); query.append(String.format(" |> range(start:%s, stop:%s)", start, stop)); } catch (ParseException e) { e.printStackTrace(); } } else { query.append("|> range(start: -30d)"); } query.append(String.format(" |> filter(fn: (r) => r[\"_measurement\"] == \"history\") |> filter(fn: (r) => r[\"imei\"] == \"%s\") |> filter(fn: (r) => r[\"_field\"] == \"jsondata\" ) |> sort(columns:[\"_time\"], desc:true) ", imei)); if (pageNo != null && pageSize != null) { query.append(String.format(" |> limit(n: %s,offset:%s)", pageSize, pageNo - 1)); } query.append(" |> yield(name: \"last\")"); System.out.println("查询语句==========:" + query); List tables = client.getQueryApi().query(query.toString()); List rerurnList = new ArrayList<>(); for (FluxTable fluxTable : tables) { List records = fluxTable.getRecords(); for (FluxRecord fluxRecord : records) { String value = (String) fluxRecord.getValueByKey("_value"); DeviceHistoryData data = JSONObject.parseObject(value, DeviceHistoryData.class); Integer singalstrength = (Integer) JSONObject.parseObject(value).get("singalstrength"); data.setSignalStrength(singalstrength); data.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Double.parseDouble(data.getTime())))); rerurnList.add(data); } } client.close(); Collections.reverse(rerurnList); return rerurnList; } /** * 获取要转存的历史influxdb数据 */ public List getOldInfluxdbData(String imei) { DeviceBelongInfo deviceBelongInfo = deviceInfoMapper.queryDeviceBelongInfo(imei); InfluxDBClient client = InfluxDBClientFactory.create(url, token.toCharArray(), org); StringBuffer query = new StringBuffer(); query.append("from(bucket: \"iot\") "); query.append("|> range(start: -1y)"); query.append(String.format(" |> filter(fn: (r) => r[\"_measurement\"] == \"history\") |> filter(fn: (r) => r[\"imei\"] == \"%s\") |> filter(fn: (r) => r[\"_field\"] == \"jsondata\" ) |> sort(columns:[\"_time\"], desc:true) ", imei)); // if (pageNo != null && pageSize != null) { // query.append(String.format(" |> limit(n: %s,offset:%s)", pageSize, pageNo - 1)); // } query.append(" |> yield(name: \"last\")"); System.out.println("查询语句==========:" + query); List tables = client.getQueryApi().query(query.toString()); List rerurnList = new ArrayList<>(); for (FluxTable fluxTable : tables) { List records = fluxTable.getRecords(); for (FluxRecord fluxRecord : records) { String value = (String) fluxRecord.getValueByKey("_value"); History history = JSONObject.parseObject(value, History.class); if (history != null) { Date createtime = history.getSenddate(); //将时间转换成Instant Instant time = null; if (createtime != null) { time = createtime.toInstant(); } if (history.getDeviceBelongInfo() == null && deviceBelongInfo != null) { history.setDeviceBelongInfo(deviceBelongInfo.getDeviceBelongInfo()); history.setHouseId(deviceBelongInfo.getHouseId()); } DeviceDataInfluxData deviceDataInfluxData = rebuildDeviceDataInfluxData(history, time); rerurnList.add(deviceDataInfluxData); } } } client.close(); Collections.reverse(rerurnList); return rerurnList; } /** * 存储设备数据到influxdb * * @param history */ public void saveDeviceDataToInfluxdb(History history) { if (history.getSenddate() == null) { return; } if (history == null || (StringUtils.isEmpty(history.getImei()))) { return; } //查询设备的所属信息 if (history != null && (history.getDeviceBelongInfo() == null || history.getHouseId() == null)) { DeviceBelongInfo deviceBelongInfo = getDeviceBelongInfo(history.getImei().trim()); if (deviceBelongInfo == null) { return; } history.setDeviceBelongInfo(deviceBelongInfo.getDeviceBelongInfo()); history.setHouseId(deviceBelongInfo.getHouseId()); } Date createtime = history.getSenddate(); //将时间转换成Instant Instant time = null; if (createtime != null) { time = createtime.toInstant(); } InfluxDBClient client = InfluxDBClientFactory.create(url, token.toCharArray()); DeviceDataInfluxData deviceDataInfluxData = rebuildDeviceDataInfluxData(history, time); try (WriteApi writeApi = client.getWriteApi()) { writeApi.writeMeasurement(DEVICEDATA_BUCKET_NAME, org, WritePrecision.NS, deviceDataInfluxData); } System.out.println("设备数据写入成功==========》" + history.getImei()); } /** * 构建Influxdb设备数据 * * @param history */ private DeviceDataInfluxData rebuildDeviceDataInfluxData(History history, Instant time) { DeviceDataInfluxData deviceDataInfluxData = new DeviceDataInfluxData(); deviceDataInfluxData.imei = history.getImei(); String value = history.getValue(); if (value != null && !value.equals("")) { String[] values = value.split(","); deviceDataInfluxData.value1 = 0; deviceDataInfluxData.value2 = 0; deviceDataInfluxData.value3 = 0; deviceDataInfluxData.value4 = 0; try { if (values.length > 0) { deviceDataInfluxData.value1 = Double.parseDouble(values[0]); } if (values.length > 1) { deviceDataInfluxData.value2 = Double.parseDouble(values[1]); } if (values.length > 2) { deviceDataInfluxData.value3 = Double.parseDouble(values[2]); } if (values.length > 3) { deviceDataInfluxData.value4 = Double.parseDouble(values[4]); } } catch (Exception e) { LOG.info(e.getMessage()); } } //从内部移动处出来,value有没有数值都进行插入 deviceDataInfluxData.battery = history.getBatterylevel(); deviceDataInfluxData.sigal = history.getSingalstrength(); deviceDataInfluxData.jsondata = JSON.toJSONString(history); deviceDataInfluxData.values = history.getValue(); deviceDataInfluxData.unit = history.getUnit(); deviceDataInfluxData.alarmtype = history.getAlarmtype(); deviceDataInfluxData.time = time != null ? time : Instant.now(); return deviceDataInfluxData; } /** * 查询设备的所属信息 */ public DeviceBelongInfo getDeviceBelongInfo(String imei) { return deviceInfoMapper.queryDeviceBelongInfo(imei); } /** * 删除掉所有的Influxdb数据 */ public void deleteDeviceData() { InfluxDBClient client = InfluxDBClientFactory.create(url, token.toCharArray()); StringBuffer query = new StringBuffer(); query.append("from(bucket: \"iot\") "); query.append(String.format(" |> filter(fn: (r) => r[\"_measurement\"] == \"history\")")); query.append("|> range(start: -36d)"); System.out.println("查询语句==========:" + query); DeleteApi deleteApi = client.getDeleteApi(); OffsetDateTime start = OffsetDateTime.of(2020, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); OffsetDateTime stop = OffsetDateTime.of(2026, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); try { // Delete data with specific time range deleteApi.delete(start, stop, "", DEVICEDATA_BUCKET_NAME, org); System.out.println("Data deleted successfully"); } catch (Exception e) { e.printStackTrace(); } finally { client.close(); } } /** * 转存设备历史数据(根据设备号查询设备历史数据) * * @param imei */ public void transferDeviceData(String imei) { //1.查询所有的设备编号 List syncDataFlags = deviceInfoMapper.querySyncDeviceFlagInfo(imei); //2.根据设备编号查询历史Influxdb所有的设备数据 if (syncDataFlags != null && syncDataFlags.size() > 0) { for (SyncDataFlag syncDataFlag : syncDataFlags) { Boolean syncDeviceData = false; List influxdbDataList = getOldInfluxdbData(syncDataFlag.getImei()); if (influxdbDataList != null && influxdbDataList.size() > 0) { for (DeviceDataInfluxData influxData : influxdbDataList) { InfluxDBClient client = InfluxDBClientFactory.create(oldurl, oldtoken.toCharArray()); //3.将设备数据保存到influxdb中 try (WriteApi writeApi = client.getWriteApi()) { writeApi.writeMeasurement(DEVICEDATA_BUCKET_NAME, oldorg, WritePrecision.NS, influxData); syncDeviceData = true; } catch (Exception e) { LOG.error("保存设备数据到influxdb失败:{}", e.getMessage()); syncDeviceData = false; if (influxData != null && influxData.jsondata != null && !influxData.jsondata.equals("")) { String message = influxData.jsondata; History history = JSON.parseObject(message, History.class); if (history != null && history.getImei() != null && !history.getImei().equals("")) { amqpService.SendMessage("shengdilandevicedataback", JSON.toJSONString(history)); } } } } } if (syncDeviceData) { //4.更新同步设备数据状态 deviceInfoMapper.updateSyncDeviceDataFlagInfo(syncDataFlag.getId(), 1); } } } } /** * 查询设备编码对应的设备数据记录数 */ public Long getDeviceDataCount(String imei) { InfluxDBClient client = InfluxDBClientFactory.create(oldurl, oldtoken.toCharArray(), oldorg); // 1. 拼接公共过滤条件片段(总条数和分页查询共用) StringBuilder filterFragment = new StringBuilder(); filterFragment.append("from(bucket: \"iot\") "); filterFragment.append("|> range(start: -400d)"); // 2. 拼接固定过滤条件(_measurement和_field,必选) filterFragment.append(" |> filter(fn: (r) => r[\"_measurement\"] == \"history\")"); filterFragment.append(" |> filter(fn: (r) => r[\"_field\"] == \"jsondata\")"); // 3. 动态拼接imei过滤条件(仅当imei非空且非空白字符串时拼接) if (imei != null && !imei.trim().isEmpty()) { filterFragment.append(String.format(" |> filter(fn: (r) => r[\"imei\"] == \"%s\")", imei.trim())); } // 5. 拼接固定排序条件(按时间倒序) // 2. 构建总条数查询子句(yield命名为total) StringBuilder totalQuery = new StringBuilder(); totalQuery.append(filterFragment); // 复用过滤条件 totalQuery.append(" |> count(column: \"_value\")"); // 统计总条数 totalQuery.append(" |> yield(name: \"total\")\n"); // 标记结果集为total System.out.println("查询数量语句:" + totalQuery.toString()); //查询总条数 long totalCount = 0; List totalTables = client.getQueryApi().query(totalQuery.toString()); for (FluxTable table : totalTables) { for (FluxRecord record : table.getRecords()) { Object total = record.getValue(); if (total != null) { totalCount = totalCount + ((Number) total).longValue(); } } } return totalCount; } }