获取环境信息

This commit is contained in:
孙小云 2026-01-30 14:06:38 +08:00
parent e5f5dc3727
commit 78c4d5268e
10 changed files with 970 additions and 0 deletions

View File

@ -0,0 +1,7 @@
package com.ruoyi.device.domain.api;
import com.ruoyi.device.domain.model.weather.Weather;
public interface IWeatherDomain {
Weather weatherInfo(String lat, String lon);
}

View File

@ -0,0 +1,196 @@
package com.ruoyi.device.domain.impl;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.device.domain.api.IWeatherDomain;
import com.ruoyi.device.domain.impl.weather.HttpUtils;
import com.ruoyi.device.domain.model.weather.Weather;
import com.ruoyi.device.domain.model.weather.WeatherResponse;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Component
public class WeatherDomainImpl implements IWeatherDomain {
String appcode = "6a152d74a3c249bfa6db6e664f2541f0";
public Weather weatherInfo(String lat, String lon) {
String host = "https://aliv8.data.moji.com";
String path = "/whapi/json/aliweather/condition";
String method = "POST";
Map<String, String> headers = new HashMap<String, String>();
//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
headers.put("Authorization", "APPCODE " + appcode);
//根据API的要求定义相对应的Content-Type
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
Map<String, String> querys = new HashMap<String, String>();
Map<String, String> bodys = new HashMap<String, String>();
bodys.put("lat", lat);
bodys.put("lon", lon);
bodys.put("token", "ff826c205f8f4a59701e64e9e64e01c4");
Weather weather = new Weather();
try {
HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
String json = EntityUtils.toString(response.getEntity());
System.out.println(json);
// 将JSON字符串转换为对象
WeatherResponse weatherResponse = JSON.parseObject(json, WeatherResponse.class);
// 降雨量枚举值0-无雨1-小雨2-中雨3-大雨
// 使用转换后的对象
if (weatherResponse != null && weatherResponse.getCode() == 0) {
//转换风速将风力等级转换为风速中间值
String windLevel = weatherResponse.getData().getCondition().getWindLevel();
weather.setWindSpeed(convertWindLevelToSpeed(windLevel));
weather.setEnvironmentTemperature(Double.valueOf(weatherResponse.getData().getCondition().getTemp()));
weather.setEnvironmentHumidity(Double.valueOf(weatherResponse.getData().getCondition().getHumidity()));
//转换降雨量
String conditionId = weatherResponse.getData().getCondition().getConditionId();
weather.setRainfall(convertConditionIdToRainfall(conditionId));
}
return weather;
} catch (Exception ignored) {
return null;
}
}
/**
* 根据天气状况ID转换为降雨量等级
* @param conditionId 天气状况ID
* @return 降雨量等级0-无雨1-小雨/小雪2-中雨/中雪3-大雨/大雪
*/
private static Double convertConditionIdToRainfall(String conditionId) {
if (conditionId == null || conditionId.isEmpty()) {
return 0.0; // 默认无雨
}
try {
int id = Integer.parseInt(conditionId);
// 小雨相关阵雨小阵雨局部阵雨小雨小雨夹雪小到中雨
if (id == 15 || id == 16 || id == 17 || id == 18 || id == 19 ||
id == 20 || id == 21 || id == 22 ||
id == 51 || id == 52 || id == 66 ||
id == 86 || id == 91) {
return 1.0; // 小雨
}
// 小雪相关阵雪小阵雪小雪小到中雪
if (id == 24 || id == 25 ||
id == 58 || id == 59 || id == 71 || id == 72 || id == 73 ||
id == 94) {
return 1.0; // 小雪
}
// 中雨相关中雨中到大雨
if (id == 53 || id == 67 || id == 92) {
return 2.0; // 中雨
}
// 中雪相关中雪
if (id == 60 || id == 61) {
return 2.0; // 中雪
}
// 大雨相关强阵雨大雨暴雨大暴雨特大暴雨大到暴雨
if (id == 23 || id == 54 || id == 55 || id == 56 || id == 57 ||
id == 68 || id == 69 || id == 70 || id == 93) {
return 3.0; // 大雨
}
// 大雪相关大雪暴雪
if (id == 62 || id == 63 || id == 74 || id == 75 || id == 76) {
return 3.0; // 大雪
}
// 雷雨相关雷阵雨雷电雷暴雷阵雨伴有冰雹
if (id == 37 || id == 38 || id == 39 || id == 40 || id == 41 ||
id == 42 || id == 43 || id == 44 || id == 45 ||
id == 87 || id == 88 || id == 89 || id == 90 || id == 599) {
return 1.0; // 雷阵雨按小雨处理
}
// 雨夹雪冻雨
if (id == 49 || id == 50 || id == 64 || id == 65) {
return 1.0; // 雨夹雪按小雨处理
}
// 冰雹冰针冰粒
if (id == 46 || id == 47 || id == 48) {
return 1.0; // 冰雹按小雨处理
}
// 通用通用
if (id == 78 || id == 77) {
return 1.0; // 通用雨/雪按小雨处理
}
// 其他情况晴天多云阴天沙尘等
return 0.0; // 无雨
} catch (NumberFormatException e) {
return 0.0; // 解析失败默认无雨
}
}
/**
* 根据风力等级转换为风速中间值单位m/s
* @param windLevel 风力等级
* @return 风速中间值
*/
private static Double convertWindLevelToSpeed(String windLevel) {
if (windLevel == null || windLevel.isEmpty()) {
return 0.1; // 默认无风的中间值
}
try {
int level = Integer.parseInt(windLevel);
switch (level) {
case 0: // 0-0.2 m/s
return 0.1;
case 1: // 0.3-1.5 m/s
return 0.9;
case 2: // 1.6-3.3 m/s
return 2.45;
case 3: // 3.4-5.4 m/s
return 4.4;
case 4: // 5.5-7.9 m/s
return 6.7;
case 5: // 8-10.7 m/s
return 9.35;
case 6: // 10.8-13.8 m/s
return 12.3;
case 7: // 13.9-17.1 m/s
return 15.5;
case 8: // 17.2-20.7 m/s
return 18.95;
case 9: // 20.8-24.4 m/s
return 22.6;
case 10: // 24.5-28.4 m/s
return 26.45;
case 11: // 28.5-32.6 m/s
return 30.55;
case 12: // 32.6-999.9 m/s (飓风)
return 516.25; // (32.6 + 999.9) / 2
default:
return 0.1; // 未知等级默认无风
}
} catch (NumberFormatException e) {
return 0.1; // 解析失败默认无风
}
}
}

View File

@ -0,0 +1,312 @@
package com.ruoyi.device.domain.impl.weather;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
//import org.apache.commons.lang.StringUtils;
import com.ruoyi.common.core.utils.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
public class HttpUtils {
/**
* get
*
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @return
* @throws Exception
*/
public static HttpResponse doGet(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpGet request = new HttpGet(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
return httpClient.execute(request);
}
/**
* post form
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @param bodys
* @return
* @throws Exception
*/
public static HttpResponse doPost(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys,
Map<String, String> bodys)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpPost request = new HttpPost(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
if (bodys != null) {
List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
for (String key : bodys.keySet()) {
nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
}
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
request.setEntity(formEntity);
}
return httpClient.execute(request);
}
/**
* Post String
*
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @param body
* @return
* @throws Exception
*/
public static HttpResponse doPost(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys,
String body)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpPost request = new HttpPost(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
if (StringUtils.isNotBlank(body)) {
request.setEntity(new StringEntity(body, "utf-8"));
}
return httpClient.execute(request);
}
/**
* Post stream
*
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @param body
* @return
* @throws Exception
*/
public static HttpResponse doPost(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys,
byte[] body)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpPost request = new HttpPost(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
if (body != null) {
request.setEntity(new ByteArrayEntity(body));
}
return httpClient.execute(request);
}
/**
* Put String
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @param body
* @return
* @throws Exception
*/
public static HttpResponse doPut(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys,
String body)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpPut request = new HttpPut(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
if (StringUtils.isNotBlank(body)) {
request.setEntity(new StringEntity(body, "utf-8"));
}
return httpClient.execute(request);
}
/**
* Put stream
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @param body
* @return
* @throws Exception
*/
public static HttpResponse doPut(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys,
byte[] body)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpPut request = new HttpPut(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
if (body != null) {
request.setEntity(new ByteArrayEntity(body));
}
return httpClient.execute(request);
}
/**
* Delete
*
* @param host
* @param path
* @param method
* @param headers
* @param querys
* @return
* @throws Exception
*/
public static HttpResponse doDelete(String host, String path, String method,
Map<String, String> headers,
Map<String, String> querys)
throws Exception {
HttpClient httpClient = wrapClient(host);
HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
request.addHeader(e.getKey(), e.getValue());
}
return httpClient.execute(request);
}
private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
StringBuilder sbUrl = new StringBuilder();
sbUrl.append(host);
if (!StringUtils.isBlank(path)) {
sbUrl.append(path);
}
if (null != querys) {
StringBuilder sbQuery = new StringBuilder();
for (Map.Entry<String, String> query : querys.entrySet()) {
if (0 < sbQuery.length()) {
sbQuery.append("&");
}
if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
sbQuery.append(query.getValue());
}
if (!StringUtils.isBlank(query.getKey())) {
sbQuery.append(query.getKey());
if (!StringUtils.isBlank(query.getValue())) {
sbQuery.append("=");
sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
}
}
}
if (0 < sbQuery.length()) {
sbUrl.append("?").append(sbQuery);
}
}
return sbUrl.toString();
}
private static HttpClient wrapClient(String host) {
HttpClient httpClient = new DefaultHttpClient();
if (host.startsWith("https://")) {
sslClient(httpClient);
}
return httpClient;
}
private static void sslClient(HttpClient httpClient) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] xcs, String str) {
}
public void checkServerTrusted(X509Certificate[] xcs, String str) {
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = httpClient.getConnectionManager();
SchemeRegistry registry = ccm.getSchemeRegistry();
registry.register(new Scheme("https", 443, ssf));
} catch (KeyManagementException ex) {
throw new RuntimeException(ex);
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
}
}

View File

@ -0,0 +1,66 @@
package com.ruoyi.device.domain.model.weather;
import java.io.Serializable;
/**
* 城市信息对象
*
* @author ruoyi
* @date 2026-01-30
*/
public class City implements Serializable
{
private static final long serialVersionUID = 1L;
/** 城市ID */
private Integer cityId;
/** 国家名称 */
private String counname;
/** 城市名称 */
private String name;
/** 省份名称 */
private String pname;
public Integer getCityId()
{
return cityId;
}
public void setCityId(Integer cityId)
{
this.cityId = cityId;
}
public String getCounname()
{
return counname;
}
public void setCounname(String counname)
{
this.counname = counname;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getPname()
{
return pname;
}
public void setPname(String pname)
{
this.pname = pname;
}
}

View File

@ -0,0 +1,209 @@
package com.ruoyi.device.domain.model.weather;
import java.io.Serializable;
/**
* 天气状况对象
*
* @author ruoyi
* @date 2026-01-30
*/
public class Condition implements Serializable
{
private static final long serialVersionUID = 1L;
/** 天气状况描述 */
private String condition;
/** 天气状况ID */
private String conditionId;
/** 湿度 */
private String humidity;
/** 图标 */
private String icon;
/** 气压 */
private String pressure;
/** 体感温度 */
private String realFeel;
/** 日出时间 */
private String sunRise;
/** 日落时间 */
private String sunSet;
/** 温度 */
private String temp;
/** 温馨提示 */
private String tips;
/** 更新时间 */
private String updatetime;
/** 紫外线指数 */
private String uvi;
/** 风向 */
private String windDir;
/** 风力等级 */
private String windLevel;
/** 风速 */
private String windSpeed;
public String getCondition()
{
return condition;
}
public void setCondition(String condition)
{
this.condition = condition;
}
public String getConditionId()
{
return conditionId;
}
public void setConditionId(String conditionId)
{
this.conditionId = conditionId;
}
public String getHumidity()
{
return humidity;
}
public void setHumidity(String humidity)
{
this.humidity = humidity;
}
public String getIcon()
{
return icon;
}
public void setIcon(String icon)
{
this.icon = icon;
}
public String getPressure()
{
return pressure;
}
public void setPressure(String pressure)
{
this.pressure = pressure;
}
public String getRealFeel()
{
return realFeel;
}
public void setRealFeel(String realFeel)
{
this.realFeel = realFeel;
}
public String getSunRise()
{
return sunRise;
}
public void setSunRise(String sunRise)
{
this.sunRise = sunRise;
}
public String getSunSet()
{
return sunSet;
}
public void setSunSet(String sunSet)
{
this.sunSet = sunSet;
}
public String getTemp()
{
return temp;
}
public void setTemp(String temp)
{
this.temp = temp;
}
public String getTips()
{
return tips;
}
public void setTips(String tips)
{
this.tips = tips;
}
public String getUpdatetime()
{
return updatetime;
}
public void setUpdatetime(String updatetime)
{
this.updatetime = updatetime;
}
public String getUvi()
{
return uvi;
}
public void setUvi(String uvi)
{
this.uvi = uvi;
}
public String getWindDir()
{
return windDir;
}
public void setWindDir(String windDir)
{
this.windDir = windDir;
}
public String getWindLevel()
{
return windLevel;
}
public void setWindLevel(String windLevel)
{
this.windLevel = windLevel;
}
public String getWindSpeed()
{
return windSpeed;
}
public void setWindSpeed(String windSpeed)
{
this.windSpeed = windSpeed;
}
}

View File

@ -0,0 +1,40 @@
package com.ruoyi.device.domain.model.weather;
import java.io.Serializable;
/**
* 响应码对象
*
* @author ruoyi
* @date 2026-01-30
*/
public class ResponseCode implements Serializable
{
private static final long serialVersionUID = 1L;
/** 响应码 */
private Integer c;
/** 响应描述 */
private String p;
public Integer getC()
{
return c;
}
public void setC(Integer c)
{
this.c = c;
}
public String getP()
{
return p;
}
public void setP(String p)
{
this.p = p;
}
}

View File

@ -0,0 +1,21 @@
package com.ruoyi.device.domain.model.weather;
import lombok.Data;
@Data
public class Weather {
/** 环境风速 */
private Double windSpeed;
/**
* 降雨量枚举值0-无雨1-小雨2-中雨3-大雨
*/
/** 环境雨量 */
private Double rainfall;
/** 环境温度 */
private Double environmentTemperature;
/** 环境湿度 */
private Double environmentHumidity;
}

View File

@ -0,0 +1,40 @@
package com.ruoyi.device.domain.model.weather;
import java.io.Serializable;
/**
* 天气数据对象
*
* @author ruoyi
* @date 2026-01-30
*/
public class WeatherData implements Serializable
{
private static final long serialVersionUID = 1L;
/** 城市信息 */
private City city;
/** 天气状况 */
private Condition condition;
public City getCity()
{
return city;
}
public void setCity(City city)
{
this.city = city;
}
public Condition getCondition()
{
return condition;
}
public void setCondition(Condition condition)
{
this.condition = condition;
}
}

View File

@ -0,0 +1,66 @@
package com.ruoyi.device.domain.model.weather;
import java.io.Serializable;
/**
* 天气API响应对象
*
* @author ruoyi
* @date 2026-01-30
*/
public class WeatherResponse implements Serializable
{
private static final long serialVersionUID = 1L;
/** 响应码 */
private Integer code;
/** 响应数据 */
private WeatherData data;
/** 响应消息 */
private String msg;
/** 响应码详情 */
private ResponseCode rc;
public Integer getCode()
{
return code;
}
public void setCode(Integer code)
{
this.code = code;
}
public WeatherData getData()
{
return data;
}
public void setData(WeatherData data)
{
this.data = data;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
public ResponseCode getRc()
{
return rc;
}
public void setRc(ResponseCode rc)
{
this.rc = rc;
}
}

View File

@ -9,6 +9,7 @@ import com.ruoyi.device.domain.model.thingsboard.AttributeMap;
import com.ruoyi.device.domain.model.thingsboard.TelemetryMap;
import com.ruoyi.device.domain.model.thingsboard.constants.DeviceAttributes;
import com.ruoyi.device.domain.model.thingsboard.constants.DeviceTelemetry;
import com.ruoyi.device.domain.model.weather.Weather;
import com.ruoyi.device.service.api.IBufferDeviceService;
import com.ruoyi.device.service.dto.AircraftDTO;
import com.ruoyi.device.service.dto.AircraftDetailDTO;
@ -60,6 +61,9 @@ public class BufferDeviceImpl implements IBufferDeviceService
@Autowired
private IPayloadDomain payloadDomain;
@Autowired
private IWeatherDomain iWeatherDomain;
@Override
public DockDetailDTO getDockDetailById(Long dockId)
{
@ -353,6 +357,15 @@ public class BufferDeviceImpl implements IBufferDeviceService
() -> log.warn("未获取到经度数据dockerDeviceIotId: {}", dockerDeviceIotId)
);
Weather weather =iWeatherDomain.weatherInfo(dto.getLatitude().toString(), dto.getLongitude().toString());
if (weather != null) {
dto.setWindSpeed(weather.getWindSpeed());
dto.setRainfall(weather.getRainfall());
dto.setEnvironmentTemperature(weather.getEnvironmentTemperature());
dto.setEnvironmentHumidity(weather.getEnvironmentHumidity());
}
// 无人机充电状态枚举值0-空闲1-充电中
telemetryMap.get(DeviceTelemetry.Drone_Charge_State_State)
.ifPresent(telemetryValue -> {