package com.ld.igds.timer;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ld.igds.constant.Constant;
import com.ld.igds.constant.RedisConst;
import com.ld.igds.data.ConfigData;
import com.ld.igds.io.constant.ProtocolEnum;
import com.ld.igds.models.WeatherConf;
import com.ld.igds.models.WeatherInfo;
import com.ld.igds.timer.rk.RkData;
import com.ld.igds.timer.rk.RkDto;
import com.ld.igds.timer.rk.RkResult;
import com.ld.igds.util.HttpUtils;
import com.ld.igds.util.RedisUtil;
import com.ld.igds.weather.CoreWeatherService;
import com.ld.igds.weather.WeatherUtil;
import com.ld.igds.weather.notify.NotifyWeatherService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author: andy.jia
* @description: 气象信息获取定时器
* @version:
*
* 风正致远购买外网气象服务:
* 气象服务:http://www.yiketianqi.com/
*
*
*
建大仁科的4G协议
*/
@Slf4j
@Component
public class WeatherTimerService {
@Resource(name = NotifyWeatherService.BEAN_ID)
private NotifyWeatherService notifyService;
@Resource(name = CoreWeatherService.BEAN_ID)
private CoreWeatherService weatherService;
@Autowired
private ConfigData configData;
@Autowired
private RedisUtil redisUtil;
@Autowired
private RestTemplate restTemplate;
public static String DEFAULT_URL = "https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=49421971&appsecret=JmJE48Fv&cityid={cityid}";
public static String DEFAULT_APP_ID = "49421971";
public static String DEFAULT_APP_SECRET = "JmJE48Fv";
/**
* 建大仁科4G平台缓存key
*/
public static String RK_WEATHER_V30_4G = "RK_WEATHER_V30_4G";
/**
* 定时获取气象信息,请注意,由于气象支持外网和自定义气象站,系统默认只执行其中一种方式
*/
public void doExe() {
log.info("===========================系统定时获获取气象信息======================");
// 获取气象信息配置
List list = weatherService.getConfData(null, null);
if (null == list || list.isEmpty()) return;
Date date = new Date();
for (WeatherConf conf : list) {
if (null == conf.getWanTag()) conf.setWanTag(Constant.YN_N);
if (null == conf.getProtocol()) conf.setProtocol(ProtocolEnum.TCP_DEFAULT.getCode());
//调用风正致远默认外网气象
if (Constant.YN_Y.equals(conf.getWanTag())) {
getWeatherByWeb(date, conf);
continue;
}
//调用建大仁科的气象
if (ProtocolEnum.RK_WEATHER_V30.getCode().equals(conf.getProtocol())) {
getWeatherByRkV30(date, conf);
continue;
}
}
}
/**
* 系统调用风正致远购买的外网天气气象协议
*
* @param date
* @param conf
* @return
*/
public WeatherInfo getWeatherByWeb(Date date, WeatherConf conf) {
if (StringUtils.isEmpty(conf.getCityId())) return null;
try {
if (null != configData.getWeatherPath()) {
DEFAULT_URL = configData.getWeatherPath();
}
String url = DEFAULT_URL.replace("{cityid}", conf.getCityId())
.replace("{appid}", DEFAULT_APP_ID)
.replace("{appsecret}", DEFAULT_APP_SECRET);
log.info("气象调用获取-url = {}", url);
String result = HttpUtils.doGet(url);
if (null == result) {
log.error("当前外网获取气象信息失败……");
return null;
}
WeatherWebDto dto = JSON.parseObject(result, WeatherWebDto.class);
if (StringUtils.isNotEmpty(dto.getErrcode())) {
log.error("当前外网获取气象信息异常:{}", dto.getErrmsg());
return null;
}
log.info("气象返回结果={}", dto.toString());
WeatherInfo info = new WeatherInfo();
info.setId(WeatherUtil.buildWeatherId(conf.getDeptId(), date));
info.setAirLevel(dto.getAir_level());
info.setCompanyId(conf.getCompanyId());
info.setDeptId(conf.getDeptId());
info.setHumidity(dto.getHumidity());
info.setPm25(dto.getAir_pm25());
info.setPressure(dto.getPressure());
info.setSource(WeatherUtil.SOURCE_02);
info.setTemp(dto.getTem());
info.setWeather(dto.getWea());
info.setWindDirection(dto.getWin());
info.setWindSpeed(dto.getWin_speed());
info.setWindMeter(dto.getWin_meter());
info.setCity(dto.getCity());
info.setUpdateTime(date);
notifyService.notify(info);
return info;
} catch (Exception e) {
log.error("气象信息获取异常:{}", e.getMessage(), e);
}
return null;
}
/**
* 根据建大仁科云V30协议获取气象信息
*
* @param date
* @param conf
*/
private void getWeatherByRkV30(Date date, WeatherConf conf) {
//若用户、密码、IP地址有一为空则返回
if (StringUtils.isEmpty(conf.getAccount())
|| StringUtils.isEmpty(conf.getPassword())
|| StringUtils.isEmpty(conf.getIp())) {
return;
}
//获取身份认证token
String token = getToken(conf);
//设置请求头参数
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("authorization", token);
String url = conf.getIp() + "/api/data/getRealTimeData";
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
HttpEntity ans = restTemplate.exchange(url, HttpMethod.GET,
new HttpEntity<>(null, httpHeaders), String.class);
String body = ans.getBody();
log.debug("-----当前建大仁科平台获取气象信息-----,返回数据={}", body);
RkResult response = JSONObject.parseObject(body, RkResult.class);
if (StringUtils.isEmpty(response.getCode()) || !"1000".equals(response.getCode())) {
log.error("当前建大仁科平台获取气象信息失败......");
return;
}
List result = JSON.parseArray(JSONObject.toJSONString(response.getData()), JSONObject.class);
JSONArray lists = (JSONArray) result.get(0).get("dataItem");
List list = JSON.parseArray(JSONObject.toJSONString(lists), RkDto.class);
if (null == list || list.isEmpty()) {
return;
}
WeatherInfo info = new WeatherInfo();
info.setId(WeatherUtil.buildWeatherId(conf.getDeptId(), date));
info.setCompanyId(conf.getCompanyId());
info.setDeptId(conf.getDeptId());
info.setSource(WeatherUtil.SOURCE_01);
List dataList;
List weatherList = new ArrayList<>();
//根据地址判断选项
for (RkDto rkDto : list) {
//温湿度
if ("11".equals(rkDto.getNodeId())) {
dataList = rkDto.getRegisterItem();
for (RkData rkData : dataList) {
//温度
if ("1".equals(rkData.getRegisterId())) {
info.setTemp(rkData.getData());
}
//湿度
if ("2".equals(rkData.getRegisterId())) {
info.setHumidity(rkData.getData());
}
}
}
//风力风速
if ("1".equals(rkDto.getNodeId())) {
dataList = rkDto.getRegisterItem();
for (RkData rkData : dataList) {
//风力
if ("1".equals(rkData.getRegisterId())) {
info.setWindSpeed(rkData.getData() + "级");
}
//风速
if ("2".equals(rkData.getRegisterId())) {
info.setWindMeter(rkData.getData());
}
}
}
//风向
if ("2".equals(rkDto.getNodeId())) {
dataList = rkDto.getRegisterItem();
for (RkData rkData : dataList) {
//风向
if ("1".equals(rkData.getRegisterId())) {
info.setWindDirection(rkData.getData());
}
}
}
//大气压
if ("14".equals(rkDto.getNodeId())) {
dataList = rkDto.getRegisterItem();
for (RkData rkData : dataList) {
//大气压
if ("2".equals(rkData.getRegisterId())) {
info.setPressure(rkData.getData());
}
}
}
//雨量
if ("21".equals(rkDto.getNodeId())) {
dataList = rkDto.getRegisterItem();
for (RkData rkData : dataList) {
// //瞬时雨量
// if("1".equals(rkData.getRegisterId())){
// info.setRainfall(rkData.getData());
// }
//当前雨量
if ("2".equals(rkData.getRegisterId())) {
info.setRainfall(rkData.getData());
}
}
}
//有无雨雪
if ("16".equals(rkDto.getNodeId())) {
weatherList = rkDto.getRegisterItem();
}
}
for (RkData rkData : weatherList) {
//天气
if ("1".equals(rkData.getRegisterId())) {
info.setWeather(rkData.getData());
//有雨雪时判断当前雨量
if ("有雨雪".equals(rkData.getData())) {
Double rainfall = Double.valueOf(info.getRainfall());
if (rainfall <= 10) {
info.setWeather("小雨");
}
if (rainfall > 10 && rainfall <= 25) {
info.setWeather("中雨");
}
if (rainfall > 25 && rainfall <= 50) {
info.setWeather("大雨");
}
if (rainfall > 50) {
info.setWeather("暴雨");
}
}
}
}
info.setUpdateTime(date);
info.setCity(conf.getCity());
notifyService.notify(info);
}
/**
* 获取身份认证的授权accessToken
*
* @param conf
* @return
*/
private String getToken(WeatherConf conf) {
//默认先从缓存获取
String key = RedisConst.buildKey(conf.getCompanyId(), RK_WEATHER_V30_4G, conf.getAccount());
String token = (String) redisUtil.get(key);
//若缓存获取为空,则通过接口获取token
if (null == token) {
String url = conf.getIp() + "/api/getToken?loginName=" + conf.getAccount() + "&password=" + conf.getPassword();
RkResult response = restTemplate.getForObject(url, RkResult.class);
if (null == response) {
log.error("当前建大仁科平台获取身份认证信息失败...");
return null;
}
log.info("获取的身份认证信息={}", response);
if (StringUtils.isEmpty(response.getCode()) || !"1000".equals(response.getCode())) {
log.error("当前建大仁科平台获取身份认证信息失败......");
return null;
}
JSONObject result = JSON.parseObject(JSONObject.toJSONString(response.getData()));
if (null == result) {
return null;
}
token = (String) result.get("token");
//将token存入缓存,
redisUtil.set(key, token, 2 * 60 * 60);
}
return token;
}
}