Merge remote-tracking branch 'origin/feature-BOX一期' into feature-BOX一期

This commit is contained in:
weiyachao 2023-09-21 18:24:33 +08:00
commit 83aca711ef
28 changed files with 760 additions and 0 deletions

View File

@ -0,0 +1,44 @@
package com.qiuguo.iot.data.request.third;
import lombok.Data;
import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author simon
* @date 2023/9/21
* @description 天气查询参数
**/
@Data
public class ThirdWeatherInfoRequest {
/*
* 1: 按小时查询 2:按天查询
*/
@NotNull
private Integer type;
/*
* 查询条数
*/
@NotNull
private Integer size;
/*
* 客户端ip
*/
private String ip;
/*
* 纬度
*/
private String lat;
/*
* 经度
*/
private String lng;
}

View File

@ -0,0 +1,26 @@
package com.qiuguo.iot.data.resp.third;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class ThirdIpInfoResp {
private Long id;
private String ip;
private Float lat;
private Float lng;
private String nation;
private String province;
private String city;
private String district;
private Integer adcode;
}

View File

@ -0,0 +1,22 @@
package com.qiuguo.iot.data.resp.third;
import lombok.Data;
import org.springframework.core.ParameterizedTypeReference;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class ThirdRpcResp <T>{
private Integer code;
private String msg;
private Boolean success;
private Boolean error;
private T data;
public static ParameterizedTypeReference<ThirdRpcResp<ThirdIpInfoResp>> getResponseIpType() {
return new ParameterizedTypeReference<ThirdRpcResp<ThirdIpInfoResp>>() {};
}
}

View File

@ -0,0 +1,11 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
import java.util.List;
@Data
public class AirQuality {
private List<WeatherTimeValue> aqi;
private List<WeatherTimeInt> pm25;
}

View File

@ -0,0 +1,30 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
import java.util.List;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class Daily {
private String status;
private List<Temperature> precipitation_08h_20h;
private List<Temperature> precipitation_20h_32h;
private List<Temperature> precipitation;
private List<Temperature> temperature;
private List<Temperature> temperature_08h_20h;
private List<Temperature> temperature_20h_32h;
private List<Wind> wind;
private List<Wind> wind_08h_20h;
private List<Wind> wind_20h_32h;
private List<Temperature> humidity;
private List<Temperature> cloudrate;
private List<Temperature> pressure;
private List<Temperature> visibility;
private List<Temperature> dswrf;
private LifeIndex life_index;
}

View File

@ -0,0 +1,22 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
import java.util.List;
@Data
public class Hourly {
private String status;
private String description;
private List<Precipitation> precipitation;
private List<WeatherTimeInt> temperature;
private List<WeatherTimeDouble> apparent_temperature;
private List<Wind> wind;
private List<WeatherTimeDouble> humidity;
private List<WeatherTimeInt> cloudrate;
private List<WeatherTimeString> skycon;
private List<WeatherTimeDouble> pressure;
private List<WeatherTimeDouble> visibility;
private List<WeatherTimeDouble> dswrf;
private AirQuality air_quality;
}

View File

@ -0,0 +1,20 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
import java.util.List;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class LifeIndex {
private List<LifeIndexDesc> ultraviolet;
private List<LifeIndexDesc> carWashing;
private List<LifeIndexDesc> dressing;
private List<LifeIndexDesc> comfort;
private List<LifeIndexDesc> coldRisk;
}

View File

@ -0,0 +1,19 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class LifeIndexDesc {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date date;
private String index;
private String desc;
}

View File

@ -0,0 +1,18 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class Precipitation {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private Integer value;
private Integer probability;
private Integer max;
private Integer min;
private Double avg;
}

View File

@ -0,0 +1,11 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
@Data
public class Result {
private Hourly hourly;
private Daily daily;
private Integer primary;
private String forecast_keypoint;
}

View File

@ -0,0 +1,22 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class Temperature {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
//天气
private Double max;
private Double min;
private Double avg;
private Double probability;
}

View File

@ -0,0 +1,9 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
@Data
public class Value {
private Integer chn;
private Integer usa;
}

View File

@ -0,0 +1,14 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class Visibility {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private double value;
}

View File

@ -0,0 +1,19 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
import java.util.List;
@Data
public class WeatherResp {
private String status;
private String api_version;
private String api_status;
private String lang;
private String unit;
private Integer tzshift;
private String timezone;
private Long server_time;
private List<Double> location;
private Result result;
}

View File

@ -0,0 +1,14 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class WeatherTimeDouble {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private Double value;
}

View File

@ -0,0 +1,18 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class WeatherTimeInt {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private Integer value;
//天气
private Double max;
private Double min;
private Double avg;
}

View File

@ -0,0 +1,14 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class WeatherTimeString {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private String value;
}

View File

@ -0,0 +1,14 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class WeatherTimeValue {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private Value value;
}

View File

@ -0,0 +1,19 @@
package com.qiuguo.iot.data.resp.third.weather;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class Wind {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm", timezone = "GMT+8")
private Date datetime;
private Double speed;
private Double direction;
private WindSpeed max;
private WindSpeed min;
private WindSpeed avg;
}

View File

@ -0,0 +1,14 @@
package com.qiuguo.iot.data.resp.third.weather;
import lombok.Data;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@Data
public class WindSpeed {
private Double speed;
private Double direction;
}

33
iot-common/iot-third/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.qiuguo.iot</groupId>
<artifactId>iot-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>iot-third</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>iot-third</name>
<description>iot-third</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.qiuguo.iot</groupId>
<artifactId>iot-base</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.qiuguo.iot</groupId>
<artifactId>iot-data</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.maven.plugin.version}</version>
<configuration>
<!--跳过对项目中main方法的查找-->
<skip>true</skip>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,30 @@
package com.qiuguo.iot.third.enums;
/**
* @author simon
* @create 2023-09-21 10:57
*/
public enum WeatherEnum {
//退款申请状态 0:待申请, 1:申请成功, 2:退款成功
QUERY_TYPE_1(1, "按小时查询"),
QUERY_TYPE_2(2, "按天查询"),
QUERY_MIN_SIZE(1, "1"),
QUERY_HOUR_MAX_SIZE(360, "360小时"),
QUERY_DAY_MAX_SIZE(15, "15天"),
;
public final String name;
public final Integer code;
WeatherEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return this.code;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,32 @@
package com.qiuguo.iot.third.service;
import com.qiuguo.iot.data.resp.third.ThirdIpInfoResp;
import com.qiuguo.iot.data.resp.third.ThirdRpcResp;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
/**
* @author simon
* @date 2023/9/21
* @description ip查询
**/
@Service
@Slf4j
public class IpService {
@Value("https://qiuguo-app.qiuguojihua.com/prod-api/third/ip/info")
public String thirdIpInfoUrl;
/**
* 查询ip信息
* @param ip
* @return
*/
public Mono<ThirdRpcResp<ThirdIpInfoResp>> getIpInfo(String ip) {
WebClient webClient = WebClient.builder().build();
return webClient.get().uri(thirdIpInfoUrl + "?ip=" + ip).retrieve().bodyToMono(ThirdRpcResp.getResponseIpType());
}
}

View File

@ -0,0 +1,108 @@
package com.qiuguo.iot.third.service;
import cn.hutool.json.JSONObject;
import com.qiuguo.iot.data.request.third.ThirdWeatherInfoRequest;
import com.qiuguo.iot.data.resp.third.ThirdIpInfoResp;
import com.qiuguo.iot.data.resp.third.ThirdRpcResp;
import com.qiuguo.iot.data.resp.third.weather.WeatherResp;
import com.qiuguo.iot.third.enums.WeatherEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.CoreSubscriber;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.annotation.Nullable;
import javax.annotation.Resource;
import java.util.regex.Pattern;
/**
* @author simon
* @date 2023/9/21
* @description 天气服务
**/
@Service
@Slf4j
@Validated
public class WeatherService {
//101.6656,39.2072/hourly?hourlysteps=1
//101.6656,39.2072/daily?dailysteps=1
@Value("https://api.caiyunapp.com/v2.6/ilUeAnf1vNkphxYS/")
private String queryWeatherUrl;
@Resource
private IpService ipService;
/**
*
* @return
*/
public Mono<WeatherResp> queryWeather(ThirdWeatherInfoRequest req) {
if (req.getType() < WeatherEnum.QUERY_TYPE_1.getCode() || req.getType() > WeatherEnum.QUERY_TYPE_2.getCode()) {
req.setType(WeatherEnum.QUERY_TYPE_1.getCode());
}
if (req.getSize() < WeatherEnum.QUERY_MIN_SIZE.getCode()) {
req.setSize(WeatherEnum.QUERY_MIN_SIZE.getCode());
}
//小时查询最大360小时
if (req.getType().equals(WeatherEnum.QUERY_TYPE_1.getCode()) && req.getSize() > WeatherEnum.QUERY_HOUR_MAX_SIZE.getCode()) {
req.setSize(WeatherEnum.QUERY_HOUR_MAX_SIZE.getCode());
}
//按天查询最多15天
if (req.getType().equals(WeatherEnum.QUERY_TYPE_2.getCode()) && req.getSize() > WeatherEnum.QUERY_DAY_MAX_SIZE.getCode()) {
req.setSize(WeatherEnum.QUERY_DAY_MAX_SIZE.getCode());
}
Mono<ThirdWeatherInfoRequest> lngLatMono = Mono.empty();
//如果经纬度为空通过ip获取经纬度
if (ObjectUtils.isEmpty(req.getLng()) || ObjectUtils.isEmpty(req.getLat())) {
if (ObjectUtils.isEmpty(req.getIp())) {
throw new RuntimeException("ip经纬度不能同时为空");
}
boolean matches = Pattern.matches("^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", req.getIp());
if (!matches) {
throw new RuntimeException("ip格式不正确");
}
lngLatMono = ipService.getIpInfo(req.getIp()).flatMap(resp -> {
if (!resp.getCode().equals(HttpStatus.OK.value())) {
return Mono.error(new RuntimeException("ip服务查询失败:" + resp.getMsg() + " " + resp.getCode()));
}
if (ObjectUtils.isEmpty(resp.getData().getLng()) || ObjectUtils.isEmpty(resp.getData().getLat())) {
return Mono.error(new RuntimeException("当前ip查询失败:" + req.getIp()));
}
req.setLng(resp.getData().getLng().toString());
req.setLat(resp.getData().getLat().toString());
return Mono.just(req);
});
} else {
lngLatMono = Mono.just(req);
}
return thirdQueryWeather(lngLatMono, req.getType(), req.getSize());
}
public Mono<WeatherResp> thirdQueryWeather(Mono<ThirdWeatherInfoRequest> lngLatMono, Integer queryType, Integer querySize) {
WebClient webClient = WebClient.builder().build();
return lngLatMono.flatMap(r -> {
if (queryType.equals(WeatherEnum.QUERY_TYPE_1.getCode())) {
queryWeatherUrl = queryWeatherUrl + r.getLng().toString() + "," + r.getLat().toString() + "/hourly?hourlysteps=" + querySize;
} else {
queryWeatherUrl = queryWeatherUrl + r.getLng().toString() + "," + r.getLat().toString() + "/daily?dailysteps=" + querySize;
}
return webClient.get().uri(queryWeatherUrl).retrieve().bodyToMono(WeatherResp.class);
});
}
}

View File

@ -0,0 +1,16 @@
package com.qiuguo.iot.third;
import com.qiuguo.iot.data.resp.third.ThirdIpInfoResp;
import com.qiuguo.iot.data.resp.third.ThirdRpcResp;
import com.qiuguo.iot.third.service.IpService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.util.concurrent.atomic.AtomicReference;
@SpringBootTest()
class IotThirdApplicationTests {
}

View File

@ -0,0 +1,46 @@
package com.qiuguo.iot.third.service;
import com.qiuguo.iot.data.resp.third.ThirdIpInfoResp;
import com.qiuguo.iot.data.resp.third.ThirdRpcResp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.test.context.SpringBootTest;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@SpringBootTest(classes = IpService.class)
class IpServiceTest {
@Resource
private IpService ipService;
@Test
void contextLoads() throws InterruptedException {
Mono<ThirdRpcResp<ThirdIpInfoResp>> ipInfo = ipService.getIpInfo("60.186.105.204");
System.out.println("contextLoads");
Mono<ThirdRpcResp<ThirdIpInfoResp>> thirdRpcRespMono = ipInfo.flatMap(resp -> {
System.out.println(resp.getData().getCity());
return Mono.just(resp);
});
thirdRpcRespMono.subscribe(System.out::println);
Thread.sleep(20000);
// StepVerifier.create(ipInfo)
// //.expectNext("Hello, World!") // 验证预期的输出值
// //.expectNext()
// .expectComplete() // 验证是否正常完成
// .verify(); // 执行验证
System.out.println("contextLoads");
}
}

View File

@ -0,0 +1,47 @@
package com.qiuguo.iot.third.service;
import cn.hutool.json.JSONObject;
import com.qiuguo.iot.data.request.third.ThirdWeatherInfoRequest;
import com.qiuguo.iot.data.resp.third.weather.WeatherResp;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
/**
* @author simon
* @date 2023/9/21
* @description
**/
@SpringBootTest(classes = {WeatherService.class, IpService.class})
class WeatherServiceTest {
@Resource
private WeatherService weatherService;
@Test
void queryWeather() throws InterruptedException {
ThirdWeatherInfoRequest thirdWeatherInfoRequest = new ThirdWeatherInfoRequest();
thirdWeatherInfoRequest.setType(2);
thirdWeatherInfoRequest.setSize(1);
thirdWeatherInfoRequest.setIp("60.186.105.204");
System.out.println(thirdWeatherInfoRequest.getIp());
Mono<WeatherResp> jsonObjectMono = weatherService.queryWeather(thirdWeatherInfoRequest);
jsonObjectMono.flatMap(r -> {
System.out.println("flatMap");
System.out.println(r.getApi_version());
return Mono.just(r);
}).subscribe(System.out::println);
Thread.sleep(20000);
System.out.println(thirdWeatherInfoRequest.getIp());
}
@Test
void thirdQueryWeather() {
}
}