Showing
1 changed file
with
146 additions
and
3 deletions
| @@ -43,7 +43,9 @@ public class CzDeviceReportService { | @@ -43,7 +43,9 @@ public class CzDeviceReportService { | ||
| 43 | " 'OFF'\n" + | 43 | " 'OFF'\n" + |
| 44 | " END AS 设备状态,\n" + | 44 | " END AS 设备状态,\n" + |
| 45 | " dc.credentials_id AS sn,\n" + | 45 | " dc.credentials_id AS sn,\n" + |
| 46 | - " de.organization_id\n" + | 46 | + " de.organization_id, \n" + |
| 47 | + " de.device_profile_id, \n" + | ||
| 48 | + " de.id \n" + | ||
| 47 | " FROM\n" + | 49 | " FROM\n" + |
| 48 | " device de\n" + | 50 | " device de\n" + |
| 49 | " LEFT JOIN ts_kv_latest tkl ON de.id = tkl.entity_id\n" + | 51 | " LEFT JOIN ts_kv_latest tkl ON de.id = tkl.entity_id\n" + |
| @@ -71,7 +73,9 @@ public class CzDeviceReportService { | @@ -71,7 +73,9 @@ public class CzDeviceReportService { | ||
| 71 | " 'RUN'\n" + | 73 | " 'RUN'\n" + |
| 72 | " END AS 设备状态,\n" + | 74 | " END AS 设备状态,\n" + |
| 73 | " dc.credentials_id AS sn,\n" + | 75 | " dc.credentials_id AS sn,\n" + |
| 74 | - " de.organization_id\n" + | 76 | + " de.organization_id, \n" + |
| 77 | + " de.device_profile_id, \n" + | ||
| 78 | + " de.id \n" + | ||
| 75 | " FROM\n" + | 79 | " FROM\n" + |
| 76 | " device de\n" + | 80 | " device de\n" + |
| 77 | " LEFT JOIN attribute_kv ak ON de.id = ak.entity_id\n" + | 81 | " LEFT JOIN attribute_kv ak ON de.id = ak.entity_id\n" + |
| @@ -93,7 +97,9 @@ public class CzDeviceReportService { | @@ -93,7 +97,9 @@ public class CzDeviceReportService { | ||
| 93 | " 'RUN'\n" + | 97 | " 'RUN'\n" + |
| 94 | " END AS 设备状态,\n" + | 98 | " END AS 设备状态,\n" + |
| 95 | " dc.credentials_id AS sn,\n" + | 99 | " dc.credentials_id AS sn,\n" + |
| 96 | - " de.organization_id\n" + | 100 | + " de.organization_id, \n" + |
| 101 | + " de.device_profile_id, \n" + | ||
| 102 | + " de.id \n" + | ||
| 97 | " FROM\n" + | 103 | " FROM\n" + |
| 98 | " device de\n" + | 104 | " device de\n" + |
| 99 | " LEFT JOIN attribute_kv ak ON de.id = ak.entity_id\n" + | 105 | " LEFT JOIN attribute_kv ak ON de.id = ak.entity_id\n" + |
| @@ -157,6 +163,8 @@ public class CzDeviceReportService { | @@ -157,6 +163,8 @@ public class CzDeviceReportService { | ||
| 157 | String deviceId = dataList.get(2).toString(); | 163 | String deviceId = dataList.get(2).toString(); |
| 158 | String status = dataList.get(1).toString(); | 164 | String status = dataList.get(1).toString(); |
| 159 | String organizeId = dataList.get(3).toString(); | 165 | String organizeId = dataList.get(3).toString(); |
| 166 | + String deviceProfileId = dataList.get(4).toString(); | ||
| 167 | + String id = dataList.get(5).toString(); | ||
| 160 | 168 | ||
| 161 | // 根据index确定clientId | 169 | // 根据index确定clientId |
| 162 | String clientId = organizeIdAndClientIdMap.get(organizeId); | 170 | String clientId = organizeIdAndClientIdMap.get(organizeId); |
| @@ -165,12 +173,18 @@ public class CzDeviceReportService { | @@ -165,12 +173,18 @@ public class CzDeviceReportService { | ||
| 165 | // 获取设备状态 | 173 | // 获取设备状态 |
| 166 | int deviceState = getDeviceState(status); | 174 | int deviceState = getDeviceState(status); |
| 167 | 175 | ||
| 176 | + // 计算当日用电量和用水量 | ||
| 177 | + double electricity = calculateDailyElectricity(id, deviceProfileId); | ||
| 178 | + double water = calculateDailyWater(id, deviceProfileId); | ||
| 179 | + | ||
| 168 | Map<String, Object> properties = new HashMap<>(5); | 180 | Map<String, Object> properties = new HashMap<>(5); |
| 169 | properties.put("type", 1); | 181 | properties.put("type", 1); |
| 170 | properties.put("state", deviceState); | 182 | properties.put("state", deviceState); |
| 171 | properties.put("time", formattedDate); | 183 | properties.put("time", formattedDate); |
| 172 | properties.put("output", 0); // 当日产量,还未确定,暂定为0 | 184 | properties.put("output", 0); // 当日产量,还未确定,暂定为0 |
| 173 | properties.put("energy", 0); // 当日能耗,还未确定,暂定为0 | 185 | properties.put("energy", 0); // 当日能耗,还未确定,暂定为0 |
| 186 | + properties.put("electricity", electricity); // 当日用电量 | ||
| 187 | + properties.put("water", water); // 当日用水量 | ||
| 174 | 188 | ||
| 175 | Map<String, Object> deviceMap = new HashMap<>(2); | 189 | Map<String, Object> deviceMap = new HashMap<>(2); |
| 176 | deviceMap.put("deviceId", deviceId); | 190 | deviceMap.put("deviceId", deviceId); |
| @@ -237,6 +251,135 @@ public class CzDeviceReportService { | @@ -237,6 +251,135 @@ public class CzDeviceReportService { | ||
| 237 | return deviceState; | 251 | return deviceState; |
| 238 | } | 252 | } |
| 239 | 253 | ||
| 254 | + /** | ||
| 255 | + * 计算当日用电量 | ||
| 256 | + * deviceProfileId = c2401630-ffec-11f0-926f-2f3182abc65f,key=64,读取dbl_v | ||
| 257 | + * @param deviceId 设备ID(entity_id) | ||
| 258 | + * @param deviceProfileId 设备配置ID | ||
| 259 | + * @return 当日用电量 | ||
| 260 | + */ | ||
| 261 | + private double calculateDailyElectricity(String deviceId, String deviceProfileId) { | ||
| 262 | + // 非用电设备类型,返回0 | ||
| 263 | + if (!"c2401630-ffec-11f0-926f-2f3182abc65f".equals(deviceProfileId)) { | ||
| 264 | + return 0; | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + String sql = "SELECT " + | ||
| 268 | + " (SELECT COALESCE(dbl_v, 0) FROM ts_kv " + | ||
| 269 | + " WHERE entity_id = ? AND key = 64 AND ts >= ? AND ts <= ? AND dbl_v IS NOT NULL " + | ||
| 270 | + " ORDER BY ts ASC LIMIT 1) AS first_value, " + | ||
| 271 | + " (SELECT COALESCE(dbl_v, 0) FROM ts_kv " + | ||
| 272 | + " WHERE entity_id = ? AND key = 64 AND ts >= ? AND ts <= ? AND dbl_v IS NOT NULL " + | ||
| 273 | + " ORDER BY ts DESC LIMIT 1) AS last_value"; | ||
| 274 | + | ||
| 275 | + return calculateDailyConsumption(deviceId, sql, "用电量"); | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + /** | ||
| 279 | + * 计算当日用水量 | ||
| 280 | + * deviceProfileId = 4e404b10-ffe7-11f0-926f-2f3182abc65f,key=83,读取dbl_v或long_v | ||
| 281 | + * @param deviceId 设备ID(entity_id) | ||
| 282 | + * @param deviceProfileId 设备配置ID | ||
| 283 | + * @return 当日用水量 | ||
| 284 | + */ | ||
| 285 | + private double calculateDailyWater(String deviceId, String deviceProfileId) { | ||
| 286 | + // 非用水设备类型,返回0 | ||
| 287 | + if (!"4e404b10-ffe7-11f0-926f-2f3182abc65f".equals(deviceProfileId)) { | ||
| 288 | + return 0; | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + String sql = "SELECT " + | ||
| 292 | + " (SELECT COALESCE(dbl_v, long_v, 0) FROM ts_kv " + | ||
| 293 | + " WHERE entity_id = ? AND key = 83 AND ts >= ? AND ts <= ? " + | ||
| 294 | + " AND (dbl_v IS NOT NULL OR long_v IS NOT NULL) " + | ||
| 295 | + " ORDER BY ts ASC LIMIT 1) AS first_value, " + | ||
| 296 | + " (SELECT COALESCE(dbl_v, long_v, 0) FROM ts_kv " + | ||
| 297 | + " WHERE entity_id = ? AND key = 83 AND ts >= ? AND ts <= ? " + | ||
| 298 | + " AND (dbl_v IS NOT NULL OR long_v IS NOT NULL) " + | ||
| 299 | + " ORDER BY ts DESC LIMIT 1) AS last_value"; | ||
| 300 | + | ||
| 301 | + return calculateDailyConsumption(deviceId, sql, "用水量"); | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + /** | ||
| 305 | + * 执行能耗计算查询 | ||
| 306 | + * @param deviceId 设备ID | ||
| 307 | + * @param sql 查询SQL | ||
| 308 | + * @param logName 日志名称 | ||
| 309 | + * @return 当日消耗量 | ||
| 310 | + */ | ||
| 311 | + private double calculateDailyConsumption(String deviceId, String sql, String logName) { | ||
| 312 | + Connection connection = null; | ||
| 313 | + PreparedStatement statement = null; | ||
| 314 | + ResultSet resultSet = null; | ||
| 315 | + HikariDataSource dataSource = null; | ||
| 316 | + | ||
| 317 | + try { | ||
| 318 | + HikariConfig config = new HikariConfig(); | ||
| 319 | + config.setJdbcUrl(jdbcUrl); | ||
| 320 | + config.setUsername(jdbcUserName); | ||
| 321 | + config.setPassword(jdbcPassword); | ||
| 322 | + config.setDriverClassName("org.postgresql.Driver"); | ||
| 323 | + config.setMaximumPoolSize(5); | ||
| 324 | + config.setMinimumIdle(5); | ||
| 325 | + config.setConnectionTimeout(60000); | ||
| 326 | + config.setConnectionTestQuery("SELECT 1"); | ||
| 327 | + | ||
| 328 | + dataSource = new HikariDataSource(config); | ||
| 329 | + connection = dataSource.getConnection(); | ||
| 330 | + | ||
| 331 | + // 获取当天开始和结束时间戳(毫秒) | ||
| 332 | + Calendar calendar = Calendar.getInstance(); | ||
| 333 | + calendar.set(Calendar.HOUR_OF_DAY, 0); | ||
| 334 | + calendar.set(Calendar.MINUTE, 0); | ||
| 335 | + calendar.set(Calendar.SECOND, 0); | ||
| 336 | + calendar.set(Calendar.MILLISECOND, 0); | ||
| 337 | + long startOfDay = calendar.getTimeInMillis(); | ||
| 338 | + calendar.set(Calendar.HOUR_OF_DAY, 23); | ||
| 339 | + calendar.set(Calendar.MINUTE, 59); | ||
| 340 | + calendar.set(Calendar.SECOND, 59); | ||
| 341 | + calendar.set(Calendar.MILLISECOND, 999); | ||
| 342 | + long endOfDay = calendar.getTimeInMillis(); | ||
| 343 | + | ||
| 344 | + statement = connection.prepareStatement(sql); | ||
| 345 | + statement.setString(1, deviceId); | ||
| 346 | + statement.setLong(2, startOfDay); | ||
| 347 | + statement.setLong(3, endOfDay); | ||
| 348 | + statement.setString(4, deviceId); | ||
| 349 | + statement.setLong(5, startOfDay); | ||
| 350 | + statement.setLong(6, endOfDay); | ||
| 351 | + | ||
| 352 | + resultSet = statement.executeQuery(); | ||
| 353 | + if (resultSet.next()) { | ||
| 354 | + double firstValue = resultSet.getDouble("first_value"); | ||
| 355 | + double lastValue = resultSet.getDouble("last_value"); | ||
| 356 | + double consumption = lastValue - firstValue; | ||
| 357 | + log.debug("设备 {} 当日{}计算: 首值={}, 末值={}, 消耗={}", deviceId, logName, firstValue, lastValue, consumption); | ||
| 358 | + return Math.max(consumption, 0); // 确保非负 | ||
| 359 | + } | ||
| 360 | + } catch (SQLException e) { | ||
| 361 | + log.error("查询设备 {} 当日{}失败: {}", deviceId, logName, e.getMessage(), e); | ||
| 362 | + } catch (Exception e) { | ||
| 363 | + log.error("计算设备 {} 当日{}时发生异常", deviceId, logName, e); | ||
| 364 | + } finally { | ||
| 365 | + try { | ||
| 366 | + if (resultSet != null) resultSet.close(); | ||
| 367 | + if (statement != null) statement.close(); | ||
| 368 | + if (connection != null) connection.close(); | ||
| 369 | + } catch (SQLException e) { | ||
| 370 | + log.error("关闭数据库资源时发生异常", e); | ||
| 371 | + } | ||
| 372 | + if (dataSource != null) { | ||
| 373 | + try { | ||
| 374 | + dataSource.close(); | ||
| 375 | + } catch (Exception e) { | ||
| 376 | + log.error("关闭HikariDataSource连接池时发生异常", e); | ||
| 377 | + } | ||
| 378 | + } | ||
| 379 | + } | ||
| 380 | + return 0; | ||
| 381 | + } | ||
| 382 | + | ||
| 240 | private List<Object> initConnectAndSelectData() { | 383 | private List<Object> initConnectAndSelectData() { |
| 241 | Connection connection = null; | 384 | Connection connection = null; |
| 242 | PreparedStatement statement = null; | 385 | PreparedStatement statement = null; |