From 4685991a2bb53e7ef93180da0d003143902b9a19 Mon Sep 17 00:00:00 2001
From: weiyachao <13526234727@126.com>
Date: Thu, 21 Sep 2023 17:46:39 +0800
Subject: [PATCH 1/3] =?UTF-8?q?gitway=20=E6=B7=BB=E5=8A=A0=E4=BE=9D?=
=?UTF-8?q?=E8=B5=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
iot-gateway/pom.xml | 12 ++-
.../config/GlobalCorsConfiguration.java | 45 ++++++++++
.../config/properties/CorsProperties.java | 48 ++++++++++
.../config/properties/XssProperties.java | 31 +++++++
.../filter/GlobalCacheRequestFilter.java | 40 +++++++++
.../handler/GatewayExceptionHandler.java | 47 ++++++++++
.../qiuguo/iot/gateway/util/WebFluxUtils.java | 88 +++++++++++++++++++
7 files changed, 310 insertions(+), 1 deletion(-)
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/XssProperties.java
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/GlobalCacheRequestFilter.java
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/handler/GatewayExceptionHandler.java
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/util/WebFluxUtils.java
diff --git a/iot-gateway/pom.xml b/iot-gateway/pom.xml
index 9516122..6e514d6 100644
--- a/iot-gateway/pom.xml
+++ b/iot-gateway/pom.xml
@@ -49,7 +49,17 @@
org.springframework.boot
spring-boot-starter-actuator
-
+
+ org.projectlombok
+ lombok
+
+
+ com.alibaba
+ fastjson
+ 1.2.83
+ compile
+
+
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java
new file mode 100644
index 0000000..7810bbd
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java
@@ -0,0 +1,45 @@
+package com.qiuguo.iot.gateway.config;
+
+import com.qiuguo.iot.gateway.config.properties.CorsProperties;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 全局跨域配置.
+ *
+ */
+@AutoConfiguration
+@EnableConfigurationProperties(CorsProperties.class)
+public class GlobalCorsConfiguration {
+
+ /**
+ * 允许跨域调用的过滤器.
+ *
+ * @param corsProperties 跨域配置
+ */
+ @Bean
+ @ConditionalOnMissingBean(CorsFilter.class)
+ public CorsFilter corsFilter(CorsProperties corsProperties) {
+ CorsConfiguration config = new CorsConfiguration();
+ // 设置允许跨域访问的域名
+ config.setAllowedOriginPatterns(corsProperties.getAllowedOriginPatterns());
+ // 设置允许跨域访问的方法
+ config.setAllowedMethods(corsProperties.getAllowedMethods());
+ // 设置允许跨域访问的请求头
+ config.setAllowedHeaders(corsProperties.getAllowedHeaders());
+ config.setExposedHeaders(corsProperties.getExposedHeaders());
+ // 允许跨越发送cookie
+ config.setAllowCredentials(corsProperties.getAllowCredentials());
+ config.setMaxAge(corsProperties.getMaxAge());
+
+ // 对接口配置跨域设置
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", config);
+ return new CorsFilter(source);
+ }
+}
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java
new file mode 100644
index 0000000..a0ef19d
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java
@@ -0,0 +1,48 @@
+package com.qiuguo.iot.gateway.config.properties;
+
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * 跨域配置.
+ *
+ * @author yangning
+ * @since 2022/11/7 14:45
+ */
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "application.cors")
+public class CorsProperties {
+
+ /**
+ * 允许跨域访问的域名.
+ */
+ private List allowedOriginPatterns;
+
+ /**
+ * 允许跨域访问的方法.
+ */
+ private List allowedMethods;
+
+ /**
+ * 允许跨域访问的请求头.
+ */
+ private List allowedHeaders;
+
+ /**
+ * 暴露的响应头.
+ */
+ private List exposedHeaders;
+
+ /**
+ * 是否允许跨域发送cookie.
+ */
+ private Boolean allowCredentials = true;
+
+ /**
+ * 跨域访问有效期.
+ */
+ private Long maxAge = 1800L;
+}
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/XssProperties.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/XssProperties.java
new file mode 100644
index 0000000..622adf3
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/XssProperties.java
@@ -0,0 +1,31 @@
+package com.qiuguo.iot.gateway.config.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+/**
+ * Xss配置.
+ *
+ * @author yangning
+ * @since 2023/4/7 18:31
+ */
+@Data
+@Component
+@RefreshScope
+@ConfigurationProperties(prefix = "security.xss")
+public class XssProperties {
+
+ /**
+ * Xss开关.
+ */
+ private Boolean enabled;
+
+ /**
+ * 排除路径.
+ */
+ private List excludeUrls = new ArrayList<>();
+}
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/GlobalCacheRequestFilter.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/GlobalCacheRequestFilter.java
new file mode 100644
index 0000000..93132e8
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/GlobalCacheRequestFilter.java
@@ -0,0 +1,40 @@
+package com.qiuguo.iot.gateway.filter;
+
+import com.qiuguo.iot.gateway.util.WebFluxUtils;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * 全局缓存获取body请求数据(解决流不能重复读取问题).
+ *
+ * @author yangning
+ * @since 2022/12/14 16:07
+ */
+@Component
+public class GlobalCacheRequestFilter implements GlobalFilter, Ordered {
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ // 只缓存json类型请求
+ // if (!WebFluxUtils.isJsonRequest(exchange)) {
+ // return chain.filter(exchange);
+ // }
+ return ServerWebExchangeUtils.cacheRequestBody(exchange, (serverHttpRequest) -> {
+ if (serverHttpRequest == exchange.getRequest()) {
+ return chain.filter(exchange);
+ }
+ return chain.filter(exchange.mutate().request(serverHttpRequest).build());
+ });
+ }
+
+ @Override
+ public int getOrder() {
+ return Ordered.HIGHEST_PRECEDENCE;
+ }
+
+}
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/handler/GatewayExceptionHandler.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/handler/GatewayExceptionHandler.java
new file mode 100644
index 0000000..9b3840c
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/handler/GatewayExceptionHandler.java
@@ -0,0 +1,47 @@
+package com.qiuguo.iot.gateway.handler;
+
+import com.qiuguo.iot.gateway.util.WebFluxUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+import org.springframework.cloud.gateway.support.NotFoundException;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * 网关统一异常处理.
+ *
+ */
+@Slf4j
+@Order(-1)
+@Configuration
+public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
+
+ @Override
+ public Mono handle(ServerWebExchange exchange, Throwable ex) {
+ final ServerHttpResponse response = exchange.getResponse();
+
+ if (exchange.getResponse().isCommitted()) {
+ return Mono.error(ex);
+ }
+
+ String msg;
+
+ if (ex instanceof NotFoundException) {
+ msg = "服务未找到";
+ } else if (ex instanceof ResponseStatusException) {
+ ResponseStatusException responseStatusException = (ResponseStatusException) ex;
+ msg = responseStatusException.getMessage();
+ } else {
+ msg = "内部服务器错误";
+ }
+
+ log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
+
+ return WebFluxUtils.webFluxResponseWriter(response, msg);
+ }
+
+}
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/util/WebFluxUtils.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/util/WebFluxUtils.java
new file mode 100644
index 0000000..5e5eef9
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/util/WebFluxUtils.java
@@ -0,0 +1,88 @@
+package com.qiuguo.iot.gateway.util;
+
+import com.alibaba.fastjson.JSON;
+import java.util.HashMap;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.util.StringUtils;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * WebFlux 工具类.
+ */
+public class WebFluxUtils {
+
+ /**
+ * 是否是Json请求.
+ *
+ * @param exchange HTTP请求
+ */
+ public static boolean isJsonRequest(ServerWebExchange exchange) {
+ String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
+ return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+ }
+
+ /**
+ * 设置webflux模型响应.
+ *
+ * @param response ServerHttpResponse
+ * @param value 响应内容
+ * @return Mono
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, Object value) {
+ return webFluxResponseWriter(response, HttpStatus.OK, value, HttpStatus.INTERNAL_SERVER_ERROR.value());
+ }
+
+ /**
+ * 设置webflux模型响应.
+ *
+ * @param response ServerHttpResponse
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return Mono
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, Object value, int code) {
+ return webFluxResponseWriter(response, HttpStatus.OK, value, code);
+ }
+
+ /**
+ * 设置webflux模型响应.
+ *
+ * @param response ServerHttpResponse
+ * @param status http状态码
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return Mono
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value,
+ int code) {
+ return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
+ }
+
+ /**
+ * 设置webflux模型响应.
+ *
+ * @param response ServerHttpResponse
+ * @param contentType content-type
+ * @param status http状态码
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return Mono
+ */
+ public static Mono webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status,
+ Object value, int code) {
+ response.setStatusCode(status);
+ response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
+ HashMap map = new HashMap<>();
+ map.put("message", value.toString());
+ map.put("status", code);
+ map.put("code", "error");
+ map.put("timestamp", System.currentTimeMillis());
+ DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(map).getBytes());
+ return response.writeWith(Mono.just(dataBuffer));
+ }
+}
From 3aecd37d4b13881fa0b3cec544ef29e84787c66b Mon Sep 17 00:00:00 2001
From: simon <861719797@qq.com>
Date: Thu, 21 Sep 2023 18:24:02 +0800
Subject: [PATCH 2/3] =?UTF-8?q?=E5=A4=A9=E6=B0=94=E3=80=81ip=E4=B8=89?=
=?UTF-8?q?=E6=96=B9=E6=9C=8D=E5=8A=A1=E5=AF=B9=E6=8E=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../third/ThirdWeatherInfoRequest.java | 44 +++++++
.../iot/data/resp/third/ThirdIpInfoResp.java | 26 +++++
.../iot/data/resp/third/ThirdRpcResp.java | 22 ++++
.../data/resp/third/weather/AirQuality.java | 11 ++
.../iot/data/resp/third/weather/Daily.java | 30 +++++
.../iot/data/resp/third/weather/Hourly.java | 22 ++++
.../data/resp/third/weather/LifeIndex.java | 20 ++++
.../resp/third/weather/LifeIndexDesc.java | 19 +++
.../resp/third/weather/Precipitation.java | 18 +++
.../iot/data/resp/third/weather/Result.java | 11 ++
.../data/resp/third/weather/Temperature.java | 22 ++++
.../iot/data/resp/third/weather/Value.java | 9 ++
.../data/resp/third/weather/Visibility.java | 14 +++
.../data/resp/third/weather/WeatherResp.java | 19 +++
.../resp/third/weather/WeatherTimeDouble.java | 14 +++
.../resp/third/weather/WeatherTimeInt.java | 18 +++
.../resp/third/weather/WeatherTimeString.java | 14 +++
.../resp/third/weather/WeatherTimeValue.java | 14 +++
.../iot/data/resp/third/weather/Wind.java | 19 +++
.../data/resp/third/weather/WindSpeed.java | 14 +++
iot-common/iot-third/.gitignore | 33 ++++++
iot-common/iot-third/pom.xml | 68 +++++++++++
.../qiuguo/iot/third/enums/WeatherEnum.java | 30 +++++
.../qiuguo/iot/third/service/IpService.java | 32 ++++++
.../iot/third/service/WeatherService.java | 108 ++++++++++++++++++
.../iot/third/IotThirdApplicationTests.java | 16 +++
.../iot/third/service/IpServiceTest.java | 46 ++++++++
.../iot/third/service/WeatherServiceTest.java | 47 ++++++++
28 files changed, 760 insertions(+)
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/request/third/ThirdWeatherInfoRequest.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdIpInfoResp.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdRpcResp.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/AirQuality.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Daily.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Hourly.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndex.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndexDesc.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Precipitation.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Result.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Temperature.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Value.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Visibility.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherResp.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeDouble.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeInt.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeString.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeValue.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Wind.java
create mode 100644 iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WindSpeed.java
create mode 100644 iot-common/iot-third/.gitignore
create mode 100644 iot-common/iot-third/pom.xml
create mode 100644 iot-common/iot-third/src/main/java/com/qiuguo/iot/third/enums/WeatherEnum.java
create mode 100644 iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/IpService.java
create mode 100644 iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/WeatherService.java
create mode 100644 iot-common/iot-third/src/test/java/com/qiuguo/iot/third/IotThirdApplicationTests.java
create mode 100644 iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/IpServiceTest.java
create mode 100644 iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/WeatherServiceTest.java
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/request/third/ThirdWeatherInfoRequest.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/request/third/ThirdWeatherInfoRequest.java
new file mode 100644
index 0000000..6d42bc3
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/request/third/ThirdWeatherInfoRequest.java
@@ -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;
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdIpInfoResp.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdIpInfoResp.java
new file mode 100644
index 0000000..4af2c98
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdIpInfoResp.java
@@ -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;
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdRpcResp.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdRpcResp.java
new file mode 100644
index 0000000..3770b3a
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/ThirdRpcResp.java
@@ -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 {
+ private Integer code;
+ private String msg;
+ private Boolean success;
+ private Boolean error;
+ private T data;
+
+ public static ParameterizedTypeReference> getResponseIpType() {
+ return new ParameterizedTypeReference>() {};
+ }
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/AirQuality.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/AirQuality.java
new file mode 100644
index 0000000..a8ed30d
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/AirQuality.java
@@ -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 aqi;
+ private List pm25;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Daily.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Daily.java
new file mode 100644
index 0000000..acbeddb
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Daily.java
@@ -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 precipitation_08h_20h;
+ private List precipitation_20h_32h;
+ private List precipitation;
+ private List temperature;
+ private List temperature_08h_20h;
+ private List temperature_20h_32h;
+ private List wind;
+ private List wind_08h_20h;
+ private List wind_20h_32h;
+ private List humidity;
+ private List cloudrate;
+ private List pressure;
+ private List visibility;
+ private List dswrf;
+ private LifeIndex life_index;
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Hourly.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Hourly.java
new file mode 100644
index 0000000..df50cf5
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Hourly.java
@@ -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;
+ private List temperature;
+ private List apparent_temperature;
+ private List wind;
+ private List humidity;
+ private List cloudrate;
+ private List skycon;
+ private List pressure;
+ private List visibility;
+ private List dswrf;
+ private AirQuality air_quality;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndex.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndex.java
new file mode 100644
index 0000000..61a79b8
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndex.java
@@ -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 ultraviolet;
+ private List carWashing;
+ private List dressing;
+ private List comfort;
+ private List coldRisk;
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndexDesc.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndexDesc.java
new file mode 100644
index 0000000..853e8d7
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/LifeIndexDesc.java
@@ -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;
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Precipitation.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Precipitation.java
new file mode 100644
index 0000000..0e3d5ed
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Precipitation.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Result.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Result.java
new file mode 100644
index 0000000..d1b46ec
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Result.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Temperature.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Temperature.java
new file mode 100644
index 0000000..9017780
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Temperature.java
@@ -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;
+}
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Value.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Value.java
new file mode 100644
index 0000000..d3bd4bc
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Value.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Visibility.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Visibility.java
new file mode 100644
index 0000000..6d5888c
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Visibility.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherResp.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherResp.java
new file mode 100644
index 0000000..15a0a45
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherResp.java
@@ -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 location;
+ private Result result;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeDouble.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeDouble.java
new file mode 100644
index 0000000..508f28e
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeDouble.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeInt.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeInt.java
new file mode 100644
index 0000000..8c6b0d2
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeInt.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeString.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeString.java
new file mode 100644
index 0000000..fbdffbf
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeString.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeValue.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeValue.java
new file mode 100644
index 0000000..23c4d16
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WeatherTimeValue.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Wind.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Wind.java
new file mode 100644
index 0000000..68563f1
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/Wind.java
@@ -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;
+}
\ No newline at end of file
diff --git a/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WindSpeed.java b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WindSpeed.java
new file mode 100644
index 0000000..bbab749
--- /dev/null
+++ b/iot-common/iot-data/src/main/java/com/qiuguo/iot/data/resp/third/weather/WindSpeed.java
@@ -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;
+}
diff --git a/iot-common/iot-third/.gitignore b/iot-common/iot-third/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/iot-common/iot-third/.gitignore
@@ -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/
diff --git a/iot-common/iot-third/pom.xml b/iot-common/iot-third/pom.xml
new file mode 100644
index 0000000..85edf18
--- /dev/null
+++ b/iot-common/iot-third/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+
+ com.qiuguo.iot
+ iot-common
+ 0.0.1-SNAPSHOT
+
+ iot-third
+ 0.0.1-SNAPSHOT
+ iot-third
+ iot-third
+
+ UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ com.qiuguo.iot
+ iot-base
+ 0.0.1-SNAPSHOT
+ compile
+
+
+ com.qiuguo.iot
+ iot-data
+ 0.0.1-SNAPSHOT
+ compile
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.maven.plugin.version}
+
+
+ true
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
diff --git a/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/enums/WeatherEnum.java b/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/enums/WeatherEnum.java
new file mode 100644
index 0000000..6c24a36
--- /dev/null
+++ b/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/enums/WeatherEnum.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/IpService.java b/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/IpService.java
new file mode 100644
index 0000000..f3e3782
--- /dev/null
+++ b/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/IpService.java
@@ -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> getIpInfo(String ip) {
+ WebClient webClient = WebClient.builder().build();
+ return webClient.get().uri(thirdIpInfoUrl + "?ip=" + ip).retrieve().bodyToMono(ThirdRpcResp.getResponseIpType());
+ }
+}
diff --git a/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/WeatherService.java b/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/WeatherService.java
new file mode 100644
index 0000000..8697eff
--- /dev/null
+++ b/iot-common/iot-third/src/main/java/com/qiuguo/iot/third/service/WeatherService.java
@@ -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 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 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 thirdQueryWeather(Mono 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);
+ });
+ }
+}
diff --git a/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/IotThirdApplicationTests.java b/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/IotThirdApplicationTests.java
new file mode 100644
index 0000000..93a6c67
--- /dev/null
+++ b/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/IotThirdApplicationTests.java
@@ -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 {
+
+}
diff --git a/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/IpServiceTest.java b/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/IpServiceTest.java
new file mode 100644
index 0000000..ee3284f
--- /dev/null
+++ b/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/IpServiceTest.java
@@ -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> ipInfo = ipService.getIpInfo("60.186.105.204");
+ System.out.println("contextLoads");
+
+ Mono> 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");
+ }
+}
\ No newline at end of file
diff --git a/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/WeatherServiceTest.java b/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/WeatherServiceTest.java
new file mode 100644
index 0000000..ef2ab9d
--- /dev/null
+++ b/iot-common/iot-third/src/test/java/com/qiuguo/iot/third/service/WeatherServiceTest.java
@@ -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 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() {
+ }
+}
\ No newline at end of file
From 962ea083f0bf2edb86a4b59afe0f71e5f4dae8f9 Mon Sep 17 00:00:00 2001
From: weiyachao <13526234727@126.com>
Date: Thu, 21 Sep 2023 18:24:27 +0800
Subject: [PATCH 3/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=99=BB=E5=BD=95?=
=?UTF-8?q?=E6=8B=A6=E6=88=AA=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../com/qiuguo/iot/base/annotation/Auth.java | 18 -----
iot-gateway/pom.xml | 10 +++
.../config/GlobalCorsConfiguration.java | 8 +--
.../config/properties/CorsProperties.java | 2 +-
.../qiuguo/iot/gateway/filter/AuthFilter.java | 69 +++++++++++++++++++
iot-gateway/src/main/resources/bootstrap.yml | 31 +++++++++
.../api/controller/user/UserController.java | 52 +++++++++-----
.../iot/user/api/filter/AuthFilter.java | 12 ----
.../src/main/resources/bootstrap.yml | 4 +-
.../src/test/java/UserTest.java | 4 +-
10 files changed, 155 insertions(+), 55 deletions(-)
delete mode 100644 iot-common/iot-base/src/main/java/com/qiuguo/iot/base/annotation/Auth.java
create mode 100644 iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/AuthFilter.java
diff --git a/iot-common/iot-base/src/main/java/com/qiuguo/iot/base/annotation/Auth.java b/iot-common/iot-base/src/main/java/com/qiuguo/iot/base/annotation/Auth.java
deleted file mode 100644
index f7dbd36..0000000
--- a/iot-common/iot-base/src/main/java/com/qiuguo/iot/base/annotation/Auth.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.qiuguo.iot.base.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 强制登陆
- *
- * @author weiyachao
- * @since 2023/9/20 15:55
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Auth {
-
-}
diff --git a/iot-gateway/pom.xml b/iot-gateway/pom.xml
index 6e514d6..04ecd3d 100644
--- a/iot-gateway/pom.xml
+++ b/iot-gateway/pom.xml
@@ -59,6 +59,16 @@
1.2.83
compile
+
+ org.springframework.boot
+ spring-boot-starter-data-redis-reactive
+
+
+ com.qiuguo.iot
+ iot-base
+ 0.0.1-SNAPSHOT
+ compile
+
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java
index 7810bbd..dfb0065 100644
--- a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/GlobalCorsConfiguration.java
@@ -13,8 +13,8 @@ import org.springframework.web.filter.CorsFilter;
* 全局跨域配置.
*
*/
-@AutoConfiguration
-@EnableConfigurationProperties(CorsProperties.class)
+// @AutoConfiguration
+// @EnableConfigurationProperties(CorsProperties.class)
public class GlobalCorsConfiguration {
/**
@@ -22,8 +22,8 @@ public class GlobalCorsConfiguration {
*
* @param corsProperties 跨域配置
*/
- @Bean
- @ConditionalOnMissingBean(CorsFilter.class)
+ // @Bean
+ // @ConditionalOnMissingBean(CorsFilter.class)
public CorsFilter corsFilter(CorsProperties corsProperties) {
CorsConfiguration config = new CorsConfiguration();
// 设置允许跨域访问的域名
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java
index a0ef19d..e9368e5 100644
--- a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/config/properties/CorsProperties.java
@@ -13,7 +13,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
*/
@Getter
@Setter
-@ConfigurationProperties(prefix = "application.cors")
+// @ConfigurationProperties(prefix = "application.cors")
public class CorsProperties {
/**
diff --git a/iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/AuthFilter.java b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/AuthFilter.java
new file mode 100644
index 0000000..3d9791d
--- /dev/null
+++ b/iot-gateway/src/main/java/com/qiuguo/iot/gateway/filter/AuthFilter.java
@@ -0,0 +1,69 @@
+package com.qiuguo.iot.gateway.filter;
+
+import com.qiuguo.iot.base.constans.RedisConstans;
+import com.qiuguo.iot.base.constans.UserAuthContains;
+import com.qiuguo.iot.gateway.config.properties.XssProperties;
+import java.time.Duration;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
+import org.springframework.http.server.RequestPath;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * XXX
+ *
+ * @author weiyachao
+ * @since 2023/9/21 17:56
+ */
+@Component
+@Slf4j
+public class AuthFilter implements GlobalFilter, Ordered {
+
+ @Autowired
+ private ReactiveStringRedisTemplate reactiveRedisTemplate;
+
+ @Autowired
+ private XssProperties xssProperties;
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ ServerHttpRequest request = exchange.getRequest();
+ String url = request.getURI().toString();
+ if (xssProperties.getExcludeUrls().contains(url)) {
+ return chain.filter(exchange);
+ }
+
+ String api_token = exchange.getRequest().getHeaders().getFirst(UserAuthContains.API_TOKEN);
+ String api_type = exchange.getRequest().getHeaders().getFirst(UserAuthContains.API_TYPE);
+ if (ObjectUtils.isEmpty(api_token) || ObjectUtils.isEmpty(api_type)) {
+ return Mono.error(new RuntimeException("未登录"));
+ }
+ String key = RedisConstans.IOT_TOKEN.concat(api_token);
+ return reactiveRedisTemplate.getExpire(key).map(Duration::getSeconds).flatMap(ttl -> {
+ if (ttl == -1) {
+ // 用户没登陆
+ return Mono.error(new RuntimeException("未登录"));
+ } else if (ttl <= 3600) {
+ // token 将要失效
+ return reactiveRedisTemplate.expire(key, Duration.ofDays(7)).then(chain.filter(exchange));
+ } else {
+ // 正常登录
+ return chain.filter(exchange);
+ }
+ });
+ }
+
+
+ @Override
+ public int getOrder() {
+ return -1;
+ }
+}
diff --git a/iot-gateway/src/main/resources/bootstrap.yml b/iot-gateway/src/main/resources/bootstrap.yml
index 8efac3c..b854733 100644
--- a/iot-gateway/src/main/resources/bootstrap.yml
+++ b/iot-gateway/src/main/resources/bootstrap.yml
@@ -19,4 +19,35 @@ spring:
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+ gateway:
+ discovery:
+ locator:
+ # 开启服务发现
+ enabled: true
+ # 忽略注册中心服务的大小写
+ lower-case-service-id: true
+ globalcors:
+ corsConfigurations:
+ '[/**]':
+ # 允许携带认证信息
+ allow-credentials: true
+ # 允许跨域的源(网站域名/ip),设置*为全部
+ allowedOriginPatterns: "*"
+ # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
+ allowedMethods: "*"
+ # 允许跨域请求里的head字段,设置*为全部
+ allowedHeaders: "*"
+ routes:
+
+# 安全配置
+security:
+ # 防止XSS攻击
+ xss:
+ enabled: true
+ # 排除的路径
+ exclude-urls:
+ - /ehs-audit/web/audit-content
+application:
+ cors:
+ allowed-crigin-patterns:
diff --git a/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/controller/user/UserController.java b/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/controller/user/UserController.java
index 1d31b5e..a99c9b0 100644
--- a/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/controller/user/UserController.java
+++ b/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/controller/user/UserController.java
@@ -1,9 +1,16 @@
package com.qiuguo.iot.user.api.controller.user;
import com.alibaba.fastjson.JSONObject;
+import com.qiuguo.iot.base.constans.RedisConstans;
+import com.qiuguo.iot.base.constans.UserAuthContains;
+import java.time.Duration;
import java.util.Objects;
+import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.ReactiveRedisTemplate;
+import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -31,7 +38,7 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL
public class UserController {
private final WebClient webClient = WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE,APPLICATION_FORM_URLENCODED_VALUE)
- .defaultHeader("Api-Type","web")
+ .defaultHeader("Api-Type","iot")
.build();
@Value("${userUrl.baseUrl}")
@@ -64,12 +71,15 @@ public class UserController {
@Value("${userUrl.editUserInfoUrl}")
private String editUserInfoUrl;
+ @Resource
+ private ReactiveStringRedisTemplate reactiveStringRedisTemplate;
+
/**
* 修改登录密码-auth
*/
@PostMapping("/change")
- public Mono change(@RequestBody JSONObject jsonObject, @RequestHeader("Api-Token") String token,
- @RequestHeader("Api-Type") String type) {
+ public Mono change(@RequestBody JSONObject jsonObject, @RequestHeader(UserAuthContains.API_TOKEN) String token,
+ @RequestHeader(UserAuthContains.API_TYPE) String type) {
WebClient authWebClient = getAuthWebClient(token, type);
return authWebClient.post().uri(baseUrl + changeUrl).bodyValue(getMultiValueMap(jsonObject)).retrieve()
.bodyToMono(JSONObject.class).doOnNext(res -> {
@@ -83,8 +93,8 @@ public class UserController {
* 账号注销-auth
*/
@PostMapping("/userCance")
- public Mono userCance(@RequestBody JSONObject jsonObject, @RequestHeader("Api-Token") String token,
- @RequestHeader("Api-Type") String type) {
+ public Mono userCance(@RequestBody JSONObject jsonObject, @RequestHeader(UserAuthContains.API_TOKEN) String token,
+ @RequestHeader(UserAuthContains.API_TYPE) String type) {
return getAuthWebClient(token, type).post().uri(baseUrl + userCancelUrl)
.bodyValue(getMultiValueMap(jsonObject))
.retrieve()
@@ -99,8 +109,8 @@ public class UserController {
* 修改用户信息-auth
*/
@PostMapping("/edit/userInfo")
- public Mono editUserInfo(@RequestBody JSONObject jsonObject, @RequestHeader("Api-Token") String token,
- @RequestHeader("Api-Type") String type) {
+ public Mono editUserInfo(@RequestBody JSONObject jsonObject, @RequestHeader(UserAuthContains.API_TOKEN) String token,
+ @RequestHeader(UserAuthContains.API_TYPE) String type) {
return webClient.mutate()
.defaultHeader("Api-Token", token)
.defaultHeader("Api-Type", type).build().post().uri(editUserInfoUrl)
@@ -117,8 +127,8 @@ public class UserController {
* 个人信息管理-auth
*/
@GetMapping("/userInfo")
- public Mono getUserInfo(@RequestHeader("Api-Token") String token,
- @RequestHeader("Api-Type") String type) {
+ public Mono getUserInfo(@RequestHeader(UserAuthContains.API_TOKEN) String token,
+ @RequestHeader(UserAuthContains.API_TYPE) String type) {
return getAuthWebClient(token, type).get().uri(userInfoUrl).retrieve()
.bodyToMono(JSONObject.class).doOnNext(res -> {
if (!Objects.equals(res.getInteger("code"), 200)) {
@@ -131,8 +141,8 @@ public class UserController {
* 是否设置登录密码-auth
*/
@GetMapping("/first/password")
- public Mono firstPassword(@RequestHeader("Api-Token") String token,
- @RequestHeader("Api-Type") String type) {
+ public Mono firstPassword(@RequestHeader(UserAuthContains.API_TOKEN) String token,
+ @RequestHeader(UserAuthContains.API_TYPE) String type) {
return getAuthWebClient(token, type).get().uri(firstPasswordUrl).retrieve()
.bodyToMono(JSONObject.class).doOnNext(res -> {
if (!Objects.equals(res.getInteger("code"), 200)) {
@@ -166,7 +176,9 @@ public class UserController {
.retrieve().bodyToMono(JSONObject.class).flatMap(res -> {
if (Objects.equals(res.getInteger("code"), 1) && !res.getString("info")
.contains("该手机号还没有注册哦")) {
- return Mono.just(res);
+ String token = res.getJSONObject("data").getJSONObject("token").getString("token");
+ return reactiveStringRedisTemplate.opsForValue()
+ .set(RedisConstans.IOT_TOKEN.concat(token), token, Duration.ofDays(7)).then(Mono.just(res));
} else if(!res.getString("info").contains("该手机号还没有注册哦")){
return Mono.error(new RuntimeException(res.getString("info")));
}else {
@@ -186,10 +198,14 @@ public class UserController {
object.add("phone", jsonObject.getString("phone"));
object.add("verify", jsonObject.getString("verify"));
return webClient.post().uri(baseUrl + smsUrl).bodyValue(object).retrieve()
- .bodyToMono(JSONObject.class).doOnNext(twoRes -> {
+ .bodyToMono(JSONObject.class).flatMap(twoRes -> {
if (!Objects.equals(twoRes.getInteger("code"), 1)) {
- throw new RuntimeException(twoRes.getString("info"));
+ return Mono.error(new RuntimeException(twoRes.getString("info")));
}
+ String token = res.getJSONObject("data").getJSONObject("token").getString("token");
+ return reactiveStringRedisTemplate.opsForValue()
+ .set(RedisConstans.IOT_TOKEN.concat(token), token, Duration.ofDays(7)).then(Mono.just(res));
+
});
}
});
@@ -205,11 +221,15 @@ public class UserController {
log.info("UserController[]loginByPwd[]jsonObject:{}", jsonObject);
return webClient.post().uri(baseUrl + pwdUrl).bodyValue(getMultiValueMap(jsonObject)).retrieve()
.bodyToMono(JSONObject.class)
- .doOnNext(res -> {
+ .flatMap(res -> {
if (!Objects.equals(res.getInteger("code"), 1)) {
- throw new RuntimeException(res.getString("info"));
+ return Mono.error(new RuntimeException(res.getString("info")));
}
+ String token = res.getJSONObject("data").getJSONObject("token").getString("token");
+ return reactiveStringRedisTemplate.opsForValue()
+ .set(RedisConstans.IOT_TOKEN.concat(token), token, Duration.ofDays(7)).then(Mono.just(res));
});
+
}
private MultiValueMap getMultiValueMap(JSONObject jsonObject) {
diff --git a/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/filter/AuthFilter.java b/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/filter/AuthFilter.java
index 82e29df..ae8d0bd 100644
--- a/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/filter/AuthFilter.java
+++ b/iot-modules/iot-box-user-api/src/main/java/com/qiuguo/iot/user/api/filter/AuthFilter.java
@@ -1,21 +1,9 @@
package com.qiuguo.iot.user.api.filter;
-import com.qiuguo.iot.base.annotation.Auth;
-import com.qiuguo.iot.base.constans.RedisConstans;
-import com.qiuguo.iot.base.constans.UserAuthContains;
-import java.lang.annotation.ElementType;
-import java.time.Duration;
-import java.util.Map;
-import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
-import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
-import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
-import org.springframework.util.ObjectUtils;
-import org.springframework.web.method.HandlerMethod;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
diff --git a/iot-modules/iot-box-user-api/src/main/resources/bootstrap.yml b/iot-modules/iot-box-user-api/src/main/resources/bootstrap.yml
index 5b7a48f..f5cc792 100644
--- a/iot-modules/iot-box-user-api/src/main/resources/bootstrap.yml
+++ b/iot-modules/iot-box-user-api/src/main/resources/bootstrap.yml
@@ -10,10 +10,10 @@ spring:
nacos:
discovery:
# 服务注册地址
- server-addr: 172.24.218.235:8848/
+ server-addr: 192.168.8.146:32470
config:
# 配置中心地址
- server-addr: 172.24.218.235:8848/
+ server-addr: 192.168.8.146:32470
# 配置文件格式
file-extension: yml
# 共享配置
diff --git a/iot-modules/iot-box-user-api/src/test/java/UserTest.java b/iot-modules/iot-box-user-api/src/test/java/UserTest.java
index 59628cf..54ce71d 100644
--- a/iot-modules/iot-box-user-api/src/test/java/UserTest.java
+++ b/iot-modules/iot-box-user-api/src/test/java/UserTest.java
@@ -18,7 +18,7 @@ import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
public class UserTest {
- public String deviceId = "6c4a153095be2b7f8baofp";
+ public String deviceId = "6cae26f5512eee7c12aqd9";
public String spaceId = "163257138";
@@ -88,7 +88,7 @@ public class UserTest {
JSONObject js3 = new JSONObject();
js3.put("code", "bright_value_v2");
js3.put("value", 10);
- commands.put("commands", Arrays.asList( js3));
+ commands.put("commands", Arrays.asList(jsonObject));
Object controlDevice = tuyaDeviceConnector.controlDevice(deviceId,commands);
System.out.println(controlDevice);