Commit 32242639cba5779a7283019f033cba66b7276682

Authored by 杨鸣坤
1 parent 7220147f

南谯经开区私有化环境同步三色灯平台数据

@@ -35,6 +35,60 @@ @@ -35,6 +35,60 @@
35 <artifactId>spring-boot-starter-test</artifactId> 35 <artifactId>spring-boot-starter-test</artifactId>
36 <scope>test</scope> 36 <scope>test</scope>
37 </dependency> 37 </dependency>
  38 + <dependency>
  39 + <groupId>com.zaxxer</groupId>
  40 + <artifactId>HikariCP</artifactId>
  41 + <version>4.0.3</version>
  42 + </dependency>
  43 + <dependency>
  44 + <groupId>com.zaxxer</groupId>
  45 + <artifactId>HikariCP-java7</artifactId>
  46 + <version>2.4.13</version>
  47 + </dependency>
  48 + <dependency>
  49 + <groupId>org.postgresql</groupId>
  50 + <artifactId>postgresql</artifactId>
  51 + <version>42.7.3</version>
  52 + </dependency>
  53 + <dependency>
  54 + <groupId>org.apache.httpcomponents</groupId>
  55 + <artifactId>httpclient</artifactId>
  56 + <version>4.5.8</version>
  57 + </dependency>
  58 + <!--工具类-->
  59 + <dependency>
  60 + <groupId>org.apache.commons</groupId>
  61 + <artifactId>commons-lang3</artifactId>
  62 + <version>3.6</version>
  63 + </dependency>
  64 +
  65 + <!--工具类-->
  66 + <dependency>
  67 + <groupId>org.apache.commons</groupId>
  68 + <artifactId>commons-collections4</artifactId>
  69 + <version>4.2</version>
  70 + </dependency>
  71 +
  72 + <dependency>
  73 + <groupId>com.alibaba</groupId>
  74 + <artifactId>fastjson</artifactId>
  75 + <version>1.2.60</version>
  76 + </dependency>
  77 + <dependency>
  78 + <groupId>org.springframework.boot</groupId>
  79 + <artifactId>spring-boot-starter-data-redis</artifactId>
  80 + <version>2.0.9.RELEASE</version>
  81 + </dependency>
  82 + <dependency>
  83 + <groupId>redis.clients</groupId>
  84 + <artifactId>jedis</artifactId>
  85 + <version>2.9.0</version>
  86 + </dependency>
  87 + <dependency>
  88 + <groupId>org.eclipse.paho</groupId>
  89 + <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
  90 + <version>1.2.5</version>
  91 + </dependency>
38 </dependencies> 92 </dependencies>
39 93
40 <build> 94 <build>
1 package com.iot.scheduler.controller; 1 package com.iot.scheduler.controller;
2 2
  3 +import com.iot.scheduler.service.YxwDevicePullService;
  4 +import jakarta.annotation.Resource;
3 import org.springframework.web.bind.annotation.GetMapping; 5 import org.springframework.web.bind.annotation.GetMapping;
4 import org.springframework.web.bind.annotation.RestController; 6 import org.springframework.web.bind.annotation.RestController;
5 7
6 @RestController 8 @RestController
7 public class HealthController { 9 public class HealthController {
8 10
  11 + @Resource
  12 + private YxwDevicePullService yxwDevicePullService;
  13 +
9 @GetMapping("/health") 14 @GetMapping("/health")
10 public String health() { 15 public String health() {
11 return "IoT Scheduler is running..."; 16 return "IoT Scheduler is running...";
12 } 17 }
  18 +
  19 + @GetMapping("/test")
  20 + public void testSend() {
  21 + yxwDevicePullService.pullDeviceAndPushToIot();
  22 + }
13 } 23 }
  1 +package com.iot.scheduler.model;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * IOT平台token
  7 + */
  8 +@Data
  9 +public class DeviceToken {
  10 + //设备凭证类型
  11 + private String credentialsType;
  12 + //设备凭证id
  13 + private String credentialsId;
  14 + //凭证值
  15 + private String credentialsValue;
  16 +
  17 +}
  1 +package com.iot.scheduler.model;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * IOT平台:设备实体
  7 + */
  8 +@Data
  9 +public class QxDeviceInfo {
  10 + //设备厂商(必填)
  11 + private String brand;
  12 +
  13 + //别名(选填)
  14 + private String alias;
  15 +
  16 + //名称(必填)
  17 + private String name;
  18 +
  19 + //设备类型(
  20 + //网关:GATEWAY, 直连:DIRECT_CONNECTION, 网关子:SENSOR)
  21 + //默认填写:DIRECT_CONNECTION
  22 + private String deviceType;
  23 +
  24 + //协议类型
  25 + //(DEFAULT,TCP,MQTT,COAP,GB
  26 + //T28281)默认填写:DEFAULT
  27 + private String transportType;
  28 +
  29 + //平台设备配置 ID
  30 + private String deviceProfileId;
  31 +
  32 + //设备配置 ID
  33 + private String profileId;
  34 +
  35 + //组织 ID
  36 + private String organizationId;
  37 +
  38 + //设备标签
  39 + private String label;
  40 +
  41 + //设备描述
  42 + private String description;
  43 +
  44 + //设备编号
  45 + private String sn;
  46 +
  47 + //设备凭证信息
  48 + private DeviceToken deviceToken;
  49 +
  50 +}
  1 +package com.iot.scheduler.model;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.Date;
  6 +
  7 +/**
  8 + * 三色灯状态详情
  9 + */
  10 +@Data
  11 +public class QxDeviceInfoDetail {
  12 + //设备状态
  13 + // RUN(运/行)/OFF(关机)/ERROR(故障)/STAND(待机)
  14 + private String status;
  15 +
  16 + //是否报警 1/0
  17 + private int alarm;
  18 +
  19 + //报警类型
  20 + private String alarmType;
  21 +
  22 + //设备序列号
  23 + private String dtuSn;
  24 +
  25 + //设备时间
  26 + private Date startTime;
  27 +
  28 +
  29 + //以下为非必填
  30 + //报警详情
  31 + private String alarmInfo;
  32 +
  33 + //用电能耗
  34 + private double eleEnergy;
  35 +
  36 + //用水量
  37 + private double waterEnergy;
  38 +
  39 + //用气量
  40 + private double gasEnergy;
  41 +
  42 + //产能
  43 + private double capacity;
  44 +
  45 + /**
  46 + * 累计产量
  47 + */
  48 + private double cumulativeOutput;
  49 +
  50 +}
  1 +package com.iot.scheduler.model;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.Map;
  6 +
  7 +/**
  8 + * 上报设备状态
  9 + */
  10 +@Data
  11 +public class ReportDevice {
  12 +
  13 + // 设备ID
  14 + private String deviceId;
  15 +
  16 + // 上报设备属性
  17 + private Map<String, Object> properties;
  18 +}
  1 +package com.iot.scheduler.service;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.alibaba.fastjson.TypeReference;
  7 +import com.iot.scheduler.model.DeviceToken;
  8 +import com.iot.scheduler.model.QxDeviceInfo;
  9 +import com.iot.scheduler.model.QxDeviceInfoDetail;
  10 +import jakarta.annotation.Resource;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.apache.commons.lang3.StringUtils;
  13 +import org.apache.http.Consts;
  14 +import org.apache.http.HttpEntity;
  15 +import org.apache.http.client.methods.CloseableHttpResponse;
  16 +import org.apache.http.client.methods.HttpGet;
  17 +import org.apache.http.client.methods.HttpPost;
  18 +import org.apache.http.entity.ContentType;
  19 +import org.apache.http.entity.StringEntity;
  20 +import org.apache.http.impl.client.CloseableHttpClient;
  21 +import org.apache.http.impl.client.HttpClients;
  22 +import org.apache.http.message.BasicHeader;
  23 +import org.apache.http.util.EntityUtils;
  24 +import org.springframework.beans.factory.annotation.Value;
  25 +import org.springframework.data.redis.core.RedisTemplate;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.util.CollectionUtils;
  28 +import org.springframework.util.LinkedMultiValueMap;
  29 +import org.springframework.util.MultiValueMap;
  30 +import org.springframework.web.util.UriComponentsBuilder;
  31 +
  32 +import java.io.ByteArrayOutputStream;
  33 +import java.io.IOException;
  34 +import java.io.InputStream;
  35 +import java.text.SimpleDateFormat;
  36 +import java.util.*;
  37 +import java.util.concurrent.TimeUnit;
  38 +
  39 +/**
  40 + * 安徽辰达半导体有限公司应用数据同步
  41 + */
  42 +@Slf4j
  43 +@Service
  44 +public class CdDevicePullService {
  45 +
  46 + @Value("${cd.iot.organizeId:}")
  47 + private String iotOrganizeId;
  48 + @Value("${cd.iot.profileId}")
  49 + private String iotProfileId;
  50 + @Value("${cd.iot.deviceProfileId}")
  51 + private String iotDeviceProfileId;
  52 + @Value("${cd.iot.userName:}")
  53 + private String iotUserName;
  54 + @Value("${cd.iot.password:}")
  55 + private String iotPassword;
  56 + @Value("${cd.iot.tokenUrl}")
  57 + private String iotTokenUrl;
  58 + @Value("${cd.iot.infoUrl}")
  59 + private String iotDeviceInfoUrl;
  60 + @Value("${cd.iot.detailUrl}")
  61 + private String iotDeviceDetailUrl;
  62 +
  63 + @Value("${device.token.url}")
  64 + private String deviceTokenUrl;
  65 + @Value("${device.token.userName}")
  66 + private String deviceUserName;
  67 + @Value("${device.token.password}")
  68 + private String devicePassword;
  69 + @Value("${device.info.url}")
  70 + private String deviceInfoUrl;
  71 + @Value("${device.detail.url}")
  72 + private String deviceDetailUrl;
  73 +
  74 + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  75 +
  76 + @Resource
  77 + private RedisTemplate<String, String> redisTemplate;
  78 +
  79 + public void pullDeviceAndPushToIot() {
  80 + String deviceResult = getDeviceInfo();
  81 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  82 + });
  83 +
  84 + JSONArray deviceInfoList = (JSONArray) deviceInfos.get("data");
  85 + List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>();
  86 + List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>();
  87 + Map<String, QxDeviceInfoDetail> qxDeviceInfoDetailMap = new HashMap<>();
  88 + for (Object o : deviceInfoList) {
  89 + JSONObject deviceInfoJson = (JSONObject) o;
  90 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  91 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  92 + qxDeviceInfo.setTransportType("DEFAULT");
  93 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  94 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  95 + qxDeviceInfo.setProfileId(iotProfileId);
  96 +// //项目状态(1:在线,2:离线,3:报警)
  97 +// Integer projectState = deviceInfoJson.getInteger("projectState");
  98 +// if (projectState != null) {
  99 +// qxDeviceInfo.setDescription(String.valueOf(projectState));
  100 +// }
  101 +
  102 + //项目类型
  103 + qxDeviceInfo.setLabel("生产设备");
  104 + //设备名称
  105 + String deviceName = deviceInfoJson.getString("deviceName");
  106 +
  107 + qxDeviceInfo.setName(deviceName);
  108 + qxDeviceInfo.setBrand(deviceName);
  109 + //序列号
  110 + String dtuSn = deviceInfoJson.getString("dtuSn");
  111 + qxDeviceInfo.setSn(dtuSn);
  112 +
  113 + DeviceToken deviceToken = new DeviceToken();
  114 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  115 + deviceToken.setCredentialsId(dtuSn);
  116 + deviceToken.setCredentialsValue(dtuSn);
  117 + qxDeviceInfo.setDeviceToken(deviceToken);
  118 + qxDeviceInfos.add(qxDeviceInfo);
  119 + //有序列号直接获取灯信息
  120 + if (StringUtils.isNotBlank(dtuSn)) {
  121 + String deviceInfoDetails = getDeviceInfoDetail(dtuSn);
  122 + if (StringUtils.isBlank(deviceInfoDetails)) {
  123 + continue;
  124 + }
  125 +
  126 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetails, new TypeReference<>() {
  127 + });
  128 +
  129 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  130 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  131 + continue;
  132 + }
  133 +
  134 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  135 + //灯详情数据
  136 + //序列号
  137 + String dtuSnDetail = deviceInfoDetailJson.getString("dtuSn");
  138 + //开始时间
  139 + String startTime = deviceInfoDetailJson.getString("startTime");
  140 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  141 + qxDeviceInfoDetail.setAlarm(0);
  142 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  143 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  144 + switch (lampState) {
  145 + case 0:
  146 + qxDeviceInfoDetail.setStatus("OFF");
  147 + break;
  148 + case 1:
  149 + qxDeviceInfoDetail.setStatus("ERROR");
  150 + qxDeviceInfoDetail.setAlarm(1);
  151 + break;
  152 + case 2:
  153 + qxDeviceInfoDetail.setStatus("STAND");
  154 + break;
  155 + case 3:
  156 + qxDeviceInfoDetail.setStatus("RUN");
  157 + break;
  158 + default:
  159 + continue;
  160 + }
  161 +
  162 + if (StringUtils.isNotBlank(startTime)) {
  163 + try {
  164 + qxDeviceInfoDetail.setStartTime(dateFormat.parse(startTime));
  165 + } catch (Exception e) {
  166 + log.error("时间格式出错");
  167 + qxDeviceInfoDetail.setStartTime(new Date());
  168 + }
  169 + } else {
  170 + qxDeviceInfoDetail.setStartTime(new Date());
  171 + }
  172 +
  173 + qxDeviceInfoDetail.setDtuSn(dtuSn);
  174 + qxDeviceInfoDetailMap.put(dtuSn, qxDeviceInfoDetail);
  175 + qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
  176 + }
  177 + }
  178 +
  179 + //将数据同步到IOT平台
  180 + Map<String, String> qxParam = new HashMap<>(2);
  181 + qxParam.put("username", iotUserName);
  182 + qxParam.put("password", iotPassword);
  183 +
  184 + HttpPost qxHttpPost = new HttpPost(iotTokenUrl);
  185 + String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam));
  186 + if (StringUtils.isBlank(qxResult)) {
  187 + return;
  188 + }
  189 + Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {
  190 + });
  191 +
  192 + String qxAccessToken = (String) qxRes.get("token");
  193 + if (StringUtils.isBlank(qxAccessToken)) {
  194 + return;
  195 + }
  196 +
  197 + BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken);
  198 + if (!CollectionUtils.isEmpty(qxDeviceInfos)) {
  199 + HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl);
  200 + qxDeviceInfoPost.addHeader(qxAuthorization);
  201 + for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) {
  202 + // todo
  203 + String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));
  204 + //log.info("同步设备信息 syncDeviceInfo:{}", syncDeviceInfo);
  205 + }
  206 + }
  207 +
  208 + if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) {
  209 + for (QxDeviceInfoDetail qxDeviceInfoDetail : qxAddDeviceInfoDetails) {
  210 + String qxDeviceInfoDetailUrlStr = iotDeviceDetailUrl + qxDeviceInfoDetail.getDtuSn() + "/telemetry";
  211 + HttpPost qxDeviceInfoDetailPost = new HttpPost(qxDeviceInfoDetailUrlStr);
  212 + qxDeviceInfoDetailPost.addHeader(qxAuthorization);
  213 + String syncDeviceInfoDetail = sendPost(qxDeviceInfoDetailPost, JSON.toJSONString(qxDeviceInfoDetail));
  214 + }
  215 + }
  216 + }
  217 +
  218 + public String getDeviceInfoDetail(String dtuSn) {
  219 + String accessToken = getAccessToken();
  220 + Map<String, String> dtuSnOb = new HashMap<>(1);
  221 + dtuSnOb.put("dtuSn", dtuSn);
  222 + Map<String, String> headerMap = new HashMap<>(1);
  223 + headerMap.put("Authorization", "Bearer " + accessToken);
  224 + String deviceInfoDetail = sendRequestGet(deviceDetailUrl, dtuSnOb, headerMap);
  225 + if (StringUtils.isBlank(deviceInfoDetail)) {
  226 + return null;
  227 + }
  228 +
  229 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetail,
  230 + new TypeReference<>() {
  231 + });
  232 + Integer deviceInfoDetailCode = (Integer) deviceInfoDetailMap.get("code");
  233 + if (deviceInfoDetailCode != 200) {
  234 + return null;
  235 + }
  236 +
  237 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  238 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  239 + return null;
  240 + }
  241 +
  242 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  243 + //灯详情数据
  244 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  245 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  246 + if (lampState == null) {
  247 + return null;
  248 + }
  249 +
  250 + return deviceInfoDetail;
  251 + }
  252 +
  253 + public String getDeviceInfo() {
  254 + String accessToken = getAccessToken();
  255 + // 初始化headerMap并设置Authorization
  256 + Map<String, String> headerMap = new HashMap<>(1);
  257 + headerMap.put("Authorization", "Bearer " + accessToken);
  258 +
  259 + Map<String, String> paramsMap = new HashMap<>();
  260 + paramsMap.put("groupName", "安徽辰达半导体有限公司");
  261 +
  262 + // 第一次请求设备信息
  263 + String deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  264 +
  265 + // 检查设备信息是否为空
  266 + if (StringUtils.isBlank(deviceResult)) {
  267 + return null;
  268 + }
  269 +
  270 + // 解析设备信息
  271 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  272 + });
  273 + Integer deviceInfoCode = (Integer) deviceInfos.get("code");
  274 +
  275 + // 如果code不为200,可能是accessToken失效,重新获取token并重试
  276 + if (deviceInfoCode != 200) {
  277 + accessToken = getAccessToken();
  278 + if (StringUtils.isEmpty(accessToken)) {
  279 + return null;
  280 + }
  281 +
  282 + // 更新headerMap中的Authorization
  283 + headerMap.put("Authorization", "Bearer " + accessToken);
  284 +
  285 + // 第二次请求设备信息
  286 + deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  287 + if (StringUtils.isBlank(deviceResult)) {
  288 + return null;
  289 + }
  290 +
  291 + // 重新解析设备信息
  292 + deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  293 + });
  294 + deviceInfoCode = (Integer) deviceInfos.get("code");
  295 +
  296 + // 如果第二次请求仍然失败,返回错误信息
  297 + if (deviceInfoCode != 200) {
  298 + return null;
  299 + }
  300 + }
  301 +
  302 + // 返回成功的设备信息
  303 + return deviceResult;
  304 + }
  305 +
  306 + private String getAccessToken() {
  307 + String accessToken = "";
  308 + String redisKey = "device_token";
  309 + if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(redisKey)) && redisTemplate.getExpire(redisKey) > 0) {
  310 + return redisTemplate.opsForValue().get(redisKey);
  311 + }
  312 +
  313 + Map<String, String> param = new HashMap<>(2);
  314 + param.put("username", deviceUserName);
  315 + param.put("password", devicePassword);
  316 + HttpPost httpPost = new HttpPost(deviceTokenUrl);
  317 + String result = sendPost(httpPost, JSON.toJSONString(param));
  318 + if (StringUtils.isBlank(result)) {
  319 + return accessToken;
  320 + }
  321 +
  322 + Map<String, Object> res = JSON.parseObject(result, new TypeReference<>() {
  323 + });
  324 +
  325 + Integer code = (Integer) res.get("code");
  326 + if (code == 200) {
  327 + JSONObject data = (JSONObject) res.get("data");
  328 + accessToken = (String) data.get("token");
  329 + redisTemplate.opsForValue().set(redisKey, accessToken, 3600, TimeUnit.SECONDS); // 一小时过期
  330 + }
  331 +
  332 + return accessToken;
  333 + }
  334 +
  335 + public static String sendRequestGet(String url, Map<String, String> params, Map<String, String> header) {
  336 + //实例化httpclient
  337 + CloseableHttpClient httpclient = HttpClients.createDefault();
  338 + url = builderUrl(url, params);
  339 + //请求结果
  340 + String content = "";
  341 + //实例化get方法
  342 + HttpGet httpget = new HttpGet(url);
  343 + if (!CollectionUtils.isEmpty(header)) {
  344 + for (Map.Entry<String, String> entry : header.entrySet()) {
  345 + httpget.setHeader(entry.getKey(), entry.getValue());
  346 + }
  347 + }
  348 +
  349 + try (CloseableHttpResponse response = httpclient.execute(httpget)) {
  350 +
  351 + //执行get方法
  352 + if (response.getStatusLine().getStatusCode() == 200) {
  353 + content = EntityUtils.toString(response.getEntity(), "UTF-8");
  354 + }
  355 + } catch (IOException e) {
  356 + log.error("sendRequest---GET Error!", e);
  357 + }
  358 + return content;
  359 + }
  360 +
  361 + private static String builderUrl(String url, Map<String, String> params) {
  362 + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);
  363 + if (!CollectionUtils.isEmpty(params)) {
  364 + MultiValueMap<String, String> paramsValue = new LinkedMultiValueMap<>();
  365 + for (Map.Entry<String, String> entry : params.entrySet()) {
  366 + paramsValue.add(entry.getKey(), entry.getValue());
  367 + }
  368 +
  369 + uriBuilder = uriBuilder.queryParams(paramsValue);
  370 + }
  371 +
  372 + return uriBuilder.toUriString();
  373 + }
  374 +
  375 + private String sendPost(HttpPost httpPost, String jsonData) {
  376 + CloseableHttpClient httpClient = HttpClients.createDefault();
  377 + StringEntity entity = new StringEntity(jsonData, ContentType.create("application/json", Consts.UTF_8));
  378 + httpPost.setEntity(entity);
  379 + String result = null;
  380 + try {
  381 + CloseableHttpResponse execute = httpClient.execute(httpPost);
  382 + HttpEntity res = execute.getEntity();
  383 + InputStream is = res.getContent();
  384 + int len;
  385 + byte[] buf = new byte[128];
  386 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  387 + while ((len = is.read(buf)) != -1) {
  388 + byteArrayOutputStream.write(buf, 0, len);
  389 + }
  390 + result = byteArrayOutputStream.toString();
  391 + } catch (IOException e) {
  392 + e.printStackTrace();
  393 + }
  394 + return result;
  395 + }
  396 +}
  1 +package com.iot.scheduler.service;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.alibaba.fastjson.TypeReference;
  7 +import com.iot.scheduler.model.DeviceToken;
  8 +import com.iot.scheduler.model.QxDeviceInfo;
  9 +import com.iot.scheduler.model.QxDeviceInfoDetail;
  10 +import jakarta.annotation.Resource;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.apache.commons.lang3.StringUtils;
  13 +import org.apache.http.Consts;
  14 +import org.apache.http.HttpEntity;
  15 +import org.apache.http.client.methods.CloseableHttpResponse;
  16 +import org.apache.http.client.methods.HttpGet;
  17 +import org.apache.http.client.methods.HttpPost;
  18 +import org.apache.http.entity.ContentType;
  19 +import org.apache.http.entity.StringEntity;
  20 +import org.apache.http.impl.client.CloseableHttpClient;
  21 +import org.apache.http.impl.client.HttpClients;
  22 +import org.apache.http.message.BasicHeader;
  23 +import org.apache.http.util.EntityUtils;
  24 +import org.springframework.beans.factory.annotation.Value;
  25 +import org.springframework.data.redis.core.RedisTemplate;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.util.CollectionUtils;
  28 +import org.springframework.util.LinkedMultiValueMap;
  29 +import org.springframework.util.MultiValueMap;
  30 +import org.springframework.web.util.UriComponentsBuilder;
  31 +
  32 +import java.io.ByteArrayOutputStream;
  33 +import java.io.IOException;
  34 +import java.io.InputStream;
  35 +import java.text.SimpleDateFormat;
  36 +import java.util.*;
  37 +import java.util.concurrent.TimeUnit;
  38 +
  39 +/**
  40 + * 安徽恩博力电器有限公司应用数据同步
  41 + */
  42 +@Slf4j
  43 +@Service
  44 +public class EblDevicePullService {
  45 +
  46 + @Value("${ebl.iot.organizeId:}")
  47 + private String iotOrganizeId;
  48 + @Value("${ebl.iot.profileId}")
  49 + private String iotProfileId;
  50 + @Value("${ebl.iot.deviceProfileId}")
  51 + private String iotDeviceProfileId;
  52 + @Value("${ebl.iot.userName:}")
  53 + private String iotUserName;
  54 + @Value("${ebl.iot.password:}")
  55 + private String iotPassword;
  56 + @Value("${ebl.iot.tokenUrl}")
  57 + private String iotTokenUrl;
  58 + @Value("${ebl.iot.infoUrl}")
  59 + private String iotDeviceInfoUrl;
  60 + @Value("${ebl.iot.detailUrl}")
  61 + private String iotDeviceDetailUrl;
  62 +
  63 + @Value("${device.token.url}")
  64 + private String deviceTokenUrl;
  65 + @Value("${device.token.userName}")
  66 + private String deviceUserName;
  67 + @Value("${device.token.password}")
  68 + private String devicePassword;
  69 + @Value("${device.info.url}")
  70 + private String deviceInfoUrl;
  71 + @Value("${device.detail.url}")
  72 + private String deviceDetailUrl;
  73 +
  74 + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  75 +
  76 + @Resource
  77 + private RedisTemplate<String, String> redisTemplate;
  78 +
  79 + public void pullDeviceAndPushToIot() {
  80 + String deviceResult = getDeviceInfo();
  81 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  82 + });
  83 +
  84 + JSONArray deviceInfoList = (JSONArray) deviceInfos.get("data");
  85 + List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>();
  86 + List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>();
  87 + Map<String, QxDeviceInfoDetail> qxDeviceInfoDetailMap = new HashMap<>();
  88 + for (Object o : deviceInfoList) {
  89 + JSONObject deviceInfoJson = (JSONObject) o;
  90 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  91 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  92 + qxDeviceInfo.setTransportType("DEFAULT");
  93 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  94 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  95 + qxDeviceInfo.setProfileId(iotProfileId);
  96 +// //项目状态(1:在线,2:离线,3:报警)
  97 +// Integer projectState = deviceInfoJson.getInteger("projectState");
  98 +// if (projectState != null) {
  99 +// qxDeviceInfo.setDescription(String.valueOf(projectState));
  100 +// }
  101 +
  102 + //项目类型
  103 + qxDeviceInfo.setLabel("生产设备");
  104 + //设备名称
  105 + String deviceName = deviceInfoJson.getString("deviceName");
  106 +
  107 + qxDeviceInfo.setName(deviceName);
  108 + qxDeviceInfo.setBrand(deviceName);
  109 + //序列号
  110 + String dtuSn = deviceInfoJson.getString("dtuSn");
  111 + qxDeviceInfo.setSn(dtuSn);
  112 +
  113 + DeviceToken deviceToken = new DeviceToken();
  114 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  115 + deviceToken.setCredentialsId(dtuSn);
  116 + deviceToken.setCredentialsValue(dtuSn);
  117 + qxDeviceInfo.setDeviceToken(deviceToken);
  118 + qxDeviceInfos.add(qxDeviceInfo);
  119 + //有序列号直接获取灯信息
  120 + if (StringUtils.isNotBlank(dtuSn)) {
  121 + String deviceInfoDetails = getDeviceInfoDetail(dtuSn);
  122 + if (StringUtils.isBlank(deviceInfoDetails)) {
  123 + continue;
  124 + }
  125 +
  126 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetails, new TypeReference<>() {
  127 + });
  128 +
  129 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  130 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  131 + continue;
  132 + }
  133 +
  134 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  135 + //灯详情数据
  136 + //序列号
  137 + String dtuSnDetail = deviceInfoDetailJson.getString("dtuSn");
  138 + //开始时间
  139 + String startTime = deviceInfoDetailJson.getString("startTime");
  140 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  141 + qxDeviceInfoDetail.setAlarm(0);
  142 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  143 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  144 + switch (lampState) {
  145 + case 0:
  146 + qxDeviceInfoDetail.setStatus("OFF");
  147 + break;
  148 + case 1:
  149 + qxDeviceInfoDetail.setStatus("ERROR");
  150 + qxDeviceInfoDetail.setAlarm(1);
  151 + break;
  152 + case 2:
  153 + qxDeviceInfoDetail.setStatus("STAND");
  154 + break;
  155 + case 3:
  156 + qxDeviceInfoDetail.setStatus("RUN");
  157 + break;
  158 + default:
  159 + continue;
  160 + }
  161 +
  162 + if (StringUtils.isNotBlank(startTime)) {
  163 + try {
  164 + qxDeviceInfoDetail.setStartTime(dateFormat.parse(startTime));
  165 + } catch (Exception e) {
  166 + log.error("时间格式出错");
  167 + qxDeviceInfoDetail.setStartTime(new Date());
  168 + }
  169 + } else {
  170 + qxDeviceInfoDetail.setStartTime(new Date());
  171 + }
  172 +
  173 + qxDeviceInfoDetail.setDtuSn(dtuSn);
  174 + qxDeviceInfoDetailMap.put(dtuSn, qxDeviceInfoDetail);
  175 + qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
  176 + }
  177 + }
  178 +
  179 + //将数据同步到IOT平台
  180 + Map<String, String> qxParam = new HashMap<>(2);
  181 + qxParam.put("username", iotUserName);
  182 + qxParam.put("password", iotPassword);
  183 +
  184 + HttpPost qxHttpPost = new HttpPost(iotTokenUrl);
  185 + String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam));
  186 + if (StringUtils.isBlank(qxResult)) {
  187 + return;
  188 + }
  189 + Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {
  190 + });
  191 +
  192 + String qxAccessToken = (String) qxRes.get("token");
  193 + if (StringUtils.isBlank(qxAccessToken)) {
  194 + return;
  195 + }
  196 +
  197 + BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken);
  198 + if (!CollectionUtils.isEmpty(qxDeviceInfos)) {
  199 + HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl);
  200 + qxDeviceInfoPost.addHeader(qxAuthorization);
  201 + for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) {
  202 + // todo
  203 + String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));
  204 + //log.info("同步设备信息 syncDeviceInfo:{}", syncDeviceInfo);
  205 + }
  206 + }
  207 +
  208 + if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) {
  209 + for (QxDeviceInfoDetail qxDeviceInfoDetail : qxAddDeviceInfoDetails) {
  210 + String qxDeviceInfoDetailUrlStr = iotDeviceDetailUrl + qxDeviceInfoDetail.getDtuSn() + "/telemetry";
  211 + HttpPost qxDeviceInfoDetailPost = new HttpPost(qxDeviceInfoDetailUrlStr);
  212 + qxDeviceInfoDetailPost.addHeader(qxAuthorization);
  213 + String syncDeviceInfoDetail = sendPost(qxDeviceInfoDetailPost, JSON.toJSONString(qxDeviceInfoDetail));
  214 + }
  215 + }
  216 + }
  217 +
  218 + public String getDeviceInfoDetail(String dtuSn) {
  219 + String accessToken = getAccessToken();
  220 + Map<String, String> dtuSnOb = new HashMap<>(1);
  221 + dtuSnOb.put("dtuSn", dtuSn);
  222 + Map<String, String> headerMap = new HashMap<>(1);
  223 + headerMap.put("Authorization", "Bearer " + accessToken);
  224 + String deviceInfoDetail = sendRequestGet(deviceDetailUrl, dtuSnOb, headerMap);
  225 + if (StringUtils.isBlank(deviceInfoDetail)) {
  226 + return null;
  227 + }
  228 +
  229 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetail,
  230 + new TypeReference<>() {
  231 + });
  232 + Integer deviceInfoDetailCode = (Integer) deviceInfoDetailMap.get("code");
  233 + if (deviceInfoDetailCode != 200) {
  234 + return null;
  235 + }
  236 +
  237 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  238 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  239 + return null;
  240 + }
  241 +
  242 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  243 + //灯详情数据
  244 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  245 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  246 + if (lampState == null) {
  247 + return null;
  248 + }
  249 +
  250 + return deviceInfoDetail;
  251 + }
  252 +
  253 + public String getDeviceInfo() {
  254 + String accessToken = getAccessToken();
  255 + // 初始化headerMap并设置Authorization
  256 + Map<String, String> headerMap = new HashMap<>(1);
  257 + headerMap.put("Authorization", "Bearer " + accessToken);
  258 +
  259 + Map<String, String> paramsMap = new HashMap<>();
  260 + paramsMap.put("groupName", "安徽恩博力电器有限公司");
  261 +
  262 + // 第一次请求设备信息
  263 + String deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  264 +
  265 + // 检查设备信息是否为空
  266 + if (StringUtils.isBlank(deviceResult)) {
  267 + return null;
  268 + }
  269 +
  270 + // 解析设备信息
  271 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  272 + });
  273 + Integer deviceInfoCode = (Integer) deviceInfos.get("code");
  274 +
  275 + // 如果code不为200,可能是accessToken失效,重新获取token并重试
  276 + if (deviceInfoCode != 200) {
  277 + accessToken = getAccessToken();
  278 + if (StringUtils.isEmpty(accessToken)) {
  279 + return null;
  280 + }
  281 +
  282 + // 更新headerMap中的Authorization
  283 + headerMap.put("Authorization", "Bearer " + accessToken);
  284 +
  285 + // 第二次请求设备信息
  286 + deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  287 + if (StringUtils.isBlank(deviceResult)) {
  288 + return null;
  289 + }
  290 +
  291 + // 重新解析设备信息
  292 + deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  293 + });
  294 + deviceInfoCode = (Integer) deviceInfos.get("code");
  295 +
  296 + // 如果第二次请求仍然失败,返回错误信息
  297 + if (deviceInfoCode != 200) {
  298 + return null;
  299 + }
  300 + }
  301 +
  302 + // 返回成功的设备信息
  303 + return deviceResult;
  304 + }
  305 +
  306 + private String getAccessToken() {
  307 + String accessToken = "";
  308 + String redisKey = "device_token";
  309 + if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(redisKey)) && redisTemplate.getExpire(redisKey) > 0) {
  310 + return redisTemplate.opsForValue().get(redisKey);
  311 + }
  312 +
  313 + Map<String, String> param = new HashMap<>(2);
  314 + param.put("username", deviceUserName);
  315 + param.put("password", devicePassword);
  316 + HttpPost httpPost = new HttpPost(deviceTokenUrl);
  317 + String result = sendPost(httpPost, JSON.toJSONString(param));
  318 + if (StringUtils.isBlank(result)) {
  319 + return accessToken;
  320 + }
  321 +
  322 + Map<String, Object> res = JSON.parseObject(result, new TypeReference<>() {
  323 + });
  324 +
  325 + Integer code = (Integer) res.get("code");
  326 + if (code == 200) {
  327 + JSONObject data = (JSONObject) res.get("data");
  328 + accessToken = (String) data.get("token");
  329 + redisTemplate.opsForValue().set(redisKey, accessToken, 3600, TimeUnit.SECONDS); // 一小时过期
  330 + }
  331 +
  332 + return accessToken;
  333 + }
  334 +
  335 + public static String sendRequestGet(String url, Map<String, String> params, Map<String, String> header) {
  336 + //实例化httpclient
  337 + CloseableHttpClient httpclient = HttpClients.createDefault();
  338 + url = builderUrl(url, params);
  339 + //请求结果
  340 + String content = "";
  341 + //实例化get方法
  342 + HttpGet httpget = new HttpGet(url);
  343 + if (!CollectionUtils.isEmpty(header)) {
  344 + for (Map.Entry<String, String> entry : header.entrySet()) {
  345 + httpget.setHeader(entry.getKey(), entry.getValue());
  346 + }
  347 + }
  348 +
  349 + try (CloseableHttpResponse response = httpclient.execute(httpget)) {
  350 +
  351 + //执行get方法
  352 + if (response.getStatusLine().getStatusCode() == 200) {
  353 + content = EntityUtils.toString(response.getEntity(), "UTF-8");
  354 + }
  355 + } catch (IOException e) {
  356 + log.error("sendRequest---GET Error!", e);
  357 + }
  358 + return content;
  359 + }
  360 +
  361 + private static String builderUrl(String url, Map<String, String> params) {
  362 + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);
  363 + if (!CollectionUtils.isEmpty(params)) {
  364 + MultiValueMap<String, String> paramsValue = new LinkedMultiValueMap<>();
  365 + for (Map.Entry<String, String> entry : params.entrySet()) {
  366 + paramsValue.add(entry.getKey(), entry.getValue());
  367 + }
  368 +
  369 + uriBuilder = uriBuilder.queryParams(paramsValue);
  370 + }
  371 +
  372 + return uriBuilder.toUriString();
  373 + }
  374 +
  375 + private String sendPost(HttpPost httpPost, String jsonData) {
  376 + CloseableHttpClient httpClient = HttpClients.createDefault();
  377 + StringEntity entity = new StringEntity(jsonData, ContentType.create("application/json", Consts.UTF_8));
  378 + httpPost.setEntity(entity);
  379 + String result = null;
  380 + try {
  381 + CloseableHttpResponse execute = httpClient.execute(httpPost);
  382 + HttpEntity res = execute.getEntity();
  383 + InputStream is = res.getContent();
  384 + int len;
  385 + byte[] buf = new byte[128];
  386 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  387 + while ((len = is.read(buf)) != -1) {
  388 + byteArrayOutputStream.write(buf, 0, len);
  389 + }
  390 + result = byteArrayOutputStream.toString();
  391 + } catch (IOException e) {
  392 + e.printStackTrace();
  393 + }
  394 + return result;
  395 + }
  396 +}
  1 +package com.iot.scheduler.service;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.alibaba.fastjson.TypeReference;
  7 +import com.iot.scheduler.model.DeviceToken;
  8 +import com.iot.scheduler.model.QxDeviceInfo;
  9 +import com.iot.scheduler.model.QxDeviceInfoDetail;
  10 +import jakarta.annotation.Resource;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.apache.commons.lang3.StringUtils;
  13 +import org.apache.http.Consts;
  14 +import org.apache.http.HttpEntity;
  15 +import org.apache.http.client.methods.CloseableHttpResponse;
  16 +import org.apache.http.client.methods.HttpGet;
  17 +import org.apache.http.client.methods.HttpPost;
  18 +import org.apache.http.entity.ContentType;
  19 +import org.apache.http.entity.StringEntity;
  20 +import org.apache.http.impl.client.CloseableHttpClient;
  21 +import org.apache.http.impl.client.HttpClients;
  22 +import org.apache.http.message.BasicHeader;
  23 +import org.apache.http.util.EntityUtils;
  24 +import org.springframework.beans.factory.annotation.Value;
  25 +import org.springframework.data.redis.core.RedisTemplate;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.util.CollectionUtils;
  28 +import org.springframework.util.LinkedMultiValueMap;
  29 +import org.springframework.util.MultiValueMap;
  30 +import org.springframework.web.util.UriComponentsBuilder;
  31 +
  32 +import java.io.ByteArrayOutputStream;
  33 +import java.io.IOException;
  34 +import java.io.InputStream;
  35 +import java.text.SimpleDateFormat;
  36 +import java.util.*;
  37 +import java.util.concurrent.TimeUnit;
  38 +
  39 +/**
  40 + * 安徽辰达半导体有限公司应用数据同步
  41 + */
  42 +@Slf4j
  43 +@Service
  44 +public class TwgdDevicePullService {
  45 +
  46 + @Value("${twgd.iot.organizeId:}")
  47 + private String iotOrganizeId;
  48 + @Value("${twgd.iot.profileId}")
  49 + private String iotProfileId;
  50 + @Value("${twgd.iot.deviceProfileId}")
  51 + private String iotDeviceProfileId;
  52 + @Value("${twgd.iot.userName:}")
  53 + private String iotUserName;
  54 + @Value("${twgd.iot.password:}")
  55 + private String iotPassword;
  56 + @Value("${twgd.iot.tokenUrl}")
  57 + private String iotTokenUrl;
  58 + @Value("${twgd.iot.infoUrl}")
  59 + private String iotDeviceInfoUrl;
  60 + @Value("${twgd.iot.detailUrl}")
  61 + private String iotDeviceDetailUrl;
  62 +
  63 + @Value("${device.token.url}")
  64 + private String deviceTokenUrl;
  65 + @Value("${device.token.userName}")
  66 + private String deviceUserName;
  67 + @Value("${device.token.password}")
  68 + private String devicePassword;
  69 + @Value("${device.info.url}")
  70 + private String deviceInfoUrl;
  71 + @Value("${device.detail.url}")
  72 + private String deviceDetailUrl;
  73 +
  74 + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  75 +
  76 + @Resource
  77 + private RedisTemplate<String, String> redisTemplate;
  78 +
  79 + public void pullDeviceAndPushToIot() {
  80 + String deviceResult = getDeviceInfo();
  81 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  82 + });
  83 +
  84 + JSONArray deviceInfoList = (JSONArray) deviceInfos.get("data");
  85 + List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>();
  86 + List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>();
  87 + Map<String, QxDeviceInfoDetail> qxDeviceInfoDetailMap = new HashMap<>();
  88 + for (Object o : deviceInfoList) {
  89 + JSONObject deviceInfoJson = (JSONObject) o;
  90 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  91 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  92 + qxDeviceInfo.setTransportType("DEFAULT");
  93 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  94 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  95 + qxDeviceInfo.setProfileId(iotProfileId);
  96 +// //项目状态(1:在线,2:离线,3:报警)
  97 +// Integer projectState = deviceInfoJson.getInteger("projectState");
  98 +// if (projectState != null) {
  99 +// qxDeviceInfo.setDescription(String.valueOf(projectState));
  100 +// }
  101 +
  102 + //项目类型
  103 + qxDeviceInfo.setLabel("生产设备");
  104 + //设备名称
  105 + String deviceName = deviceInfoJson.getString("deviceName");
  106 +
  107 + qxDeviceInfo.setName(deviceName);
  108 + qxDeviceInfo.setBrand(deviceName);
  109 + //序列号
  110 + String dtuSn = deviceInfoJson.getString("dtuSn");
  111 + qxDeviceInfo.setSn(dtuSn);
  112 +
  113 + DeviceToken deviceToken = new DeviceToken();
  114 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  115 + deviceToken.setCredentialsId(dtuSn);
  116 + deviceToken.setCredentialsValue(dtuSn);
  117 + qxDeviceInfo.setDeviceToken(deviceToken);
  118 + qxDeviceInfos.add(qxDeviceInfo);
  119 + //有序列号直接获取灯信息
  120 + if (StringUtils.isNotBlank(dtuSn)) {
  121 + String deviceInfoDetails = getDeviceInfoDetail(dtuSn);
  122 + if (StringUtils.isBlank(deviceInfoDetails)) {
  123 + continue;
  124 + }
  125 +
  126 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetails, new TypeReference<>() {
  127 + });
  128 +
  129 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  130 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  131 + continue;
  132 + }
  133 +
  134 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  135 + //灯详情数据
  136 + //序列号
  137 + String dtuSnDetail = deviceInfoDetailJson.getString("dtuSn");
  138 + //开始时间
  139 + String startTime = deviceInfoDetailJson.getString("startTime");
  140 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  141 + qxDeviceInfoDetail.setAlarm(0);
  142 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  143 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  144 + switch (lampState) {
  145 + case 0:
  146 + qxDeviceInfoDetail.setStatus("OFF");
  147 + break;
  148 + case 1:
  149 + qxDeviceInfoDetail.setStatus("ERROR");
  150 + qxDeviceInfoDetail.setAlarm(1);
  151 + break;
  152 + case 2:
  153 + qxDeviceInfoDetail.setStatus("STAND");
  154 + break;
  155 + case 3:
  156 + qxDeviceInfoDetail.setStatus("RUN");
  157 + break;
  158 + default:
  159 + continue;
  160 + }
  161 +
  162 + if (StringUtils.isNotBlank(startTime)) {
  163 + try {
  164 + qxDeviceInfoDetail.setStartTime(dateFormat.parse(startTime));
  165 + } catch (Exception e) {
  166 + log.error("时间格式出错");
  167 + qxDeviceInfoDetail.setStartTime(new Date());
  168 + }
  169 + } else {
  170 + qxDeviceInfoDetail.setStartTime(new Date());
  171 + }
  172 +
  173 + qxDeviceInfoDetail.setDtuSn(dtuSn);
  174 + qxDeviceInfoDetailMap.put(dtuSn, qxDeviceInfoDetail);
  175 + qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
  176 + }
  177 + }
  178 +
  179 + //将数据同步到IOT平台
  180 + Map<String, String> qxParam = new HashMap<>(2);
  181 + qxParam.put("username", iotUserName);
  182 + qxParam.put("password", iotPassword);
  183 +
  184 + HttpPost qxHttpPost = new HttpPost(iotTokenUrl);
  185 + String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam));
  186 + if (StringUtils.isBlank(qxResult)) {
  187 + return;
  188 + }
  189 + Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {
  190 + });
  191 +
  192 + String qxAccessToken = (String) qxRes.get("token");
  193 + if (StringUtils.isBlank(qxAccessToken)) {
  194 + return;
  195 + }
  196 +
  197 + BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken);
  198 + if (!CollectionUtils.isEmpty(qxDeviceInfos)) {
  199 + HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl);
  200 + qxDeviceInfoPost.addHeader(qxAuthorization);
  201 + for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) {
  202 + // todo
  203 + String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));
  204 + //log.info("同步设备信息 syncDeviceInfo:{}", syncDeviceInfo);
  205 + }
  206 + }
  207 +
  208 + if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) {
  209 + for (QxDeviceInfoDetail qxDeviceInfoDetail : qxAddDeviceInfoDetails) {
  210 + String qxDeviceInfoDetailUrlStr = iotDeviceDetailUrl + qxDeviceInfoDetail.getDtuSn() + "/telemetry";
  211 + HttpPost qxDeviceInfoDetailPost = new HttpPost(qxDeviceInfoDetailUrlStr);
  212 + qxDeviceInfoDetailPost.addHeader(qxAuthorization);
  213 + String syncDeviceInfoDetail = sendPost(qxDeviceInfoDetailPost, JSON.toJSONString(qxDeviceInfoDetail));
  214 + }
  215 + }
  216 + }
  217 +
  218 + public String getDeviceInfoDetail(String dtuSn) {
  219 + String accessToken = getAccessToken();
  220 + Map<String, String> dtuSnOb = new HashMap<>(1);
  221 + dtuSnOb.put("dtuSn", dtuSn);
  222 + Map<String, String> headerMap = new HashMap<>(1);
  223 + headerMap.put("Authorization", "Bearer " + accessToken);
  224 + String deviceInfoDetail = sendRequestGet(deviceDetailUrl, dtuSnOb, headerMap);
  225 + if (StringUtils.isBlank(deviceInfoDetail)) {
  226 + return null;
  227 + }
  228 +
  229 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetail,
  230 + new TypeReference<>() {
  231 + });
  232 + Integer deviceInfoDetailCode = (Integer) deviceInfoDetailMap.get("code");
  233 + if (deviceInfoDetailCode != 200) {
  234 + return null;
  235 + }
  236 +
  237 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  238 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  239 + return null;
  240 + }
  241 +
  242 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  243 + //灯详情数据
  244 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  245 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  246 + if (lampState == null) {
  247 + return null;
  248 + }
  249 +
  250 + return deviceInfoDetail;
  251 + }
  252 +
  253 + public String getDeviceInfo() {
  254 + String accessToken = getAccessToken();
  255 + // 初始化headerMap并设置Authorization
  256 + Map<String, String> headerMap = new HashMap<>(1);
  257 + headerMap.put("Authorization", "Bearer " + accessToken);
  258 +
  259 + Map<String, String> paramsMap = new HashMap<>();
  260 + paramsMap.put("groupName", "拓维光电材料(滁州)有限公司");
  261 +
  262 + // 第一次请求设备信息
  263 + String deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  264 +
  265 + // 检查设备信息是否为空
  266 + if (StringUtils.isBlank(deviceResult)) {
  267 + return null;
  268 + }
  269 +
  270 + // 解析设备信息
  271 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  272 + });
  273 + Integer deviceInfoCode = (Integer) deviceInfos.get("code");
  274 +
  275 + // 如果code不为200,可能是accessToken失效,重新获取token并重试
  276 + if (deviceInfoCode != 200) {
  277 + accessToken = getAccessToken();
  278 + if (StringUtils.isEmpty(accessToken)) {
  279 + return null;
  280 + }
  281 +
  282 + // 更新headerMap中的Authorization
  283 + headerMap.put("Authorization", "Bearer " + accessToken);
  284 +
  285 + // 第二次请求设备信息
  286 + deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  287 + if (StringUtils.isBlank(deviceResult)) {
  288 + return null;
  289 + }
  290 +
  291 + // 重新解析设备信息
  292 + deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  293 + });
  294 + deviceInfoCode = (Integer) deviceInfos.get("code");
  295 +
  296 + // 如果第二次请求仍然失败,返回错误信息
  297 + if (deviceInfoCode != 200) {
  298 + return null;
  299 + }
  300 + }
  301 +
  302 + // 返回成功的设备信息
  303 + return deviceResult;
  304 + }
  305 +
  306 + private String getAccessToken() {
  307 + String accessToken = "";
  308 + String redisKey = "device_token";
  309 + if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(redisKey)) && redisTemplate.getExpire(redisKey) > 0) {
  310 + return redisTemplate.opsForValue().get(redisKey);
  311 + }
  312 +
  313 + Map<String, String> param = new HashMap<>(2);
  314 + param.put("username", deviceUserName);
  315 + param.put("password", devicePassword);
  316 + HttpPost httpPost = new HttpPost(deviceTokenUrl);
  317 + String result = sendPost(httpPost, JSON.toJSONString(param));
  318 + if (StringUtils.isBlank(result)) {
  319 + return accessToken;
  320 + }
  321 +
  322 + Map<String, Object> res = JSON.parseObject(result, new TypeReference<>() {
  323 + });
  324 +
  325 + Integer code = (Integer) res.get("code");
  326 + if (code == 200) {
  327 + JSONObject data = (JSONObject) res.get("data");
  328 + accessToken = (String) data.get("token");
  329 + redisTemplate.opsForValue().set(redisKey, accessToken, 3600, TimeUnit.SECONDS); // 一小时过期
  330 + }
  331 +
  332 + return accessToken;
  333 + }
  334 +
  335 + public static String sendRequestGet(String url, Map<String, String> params, Map<String, String> header) {
  336 + //实例化httpclient
  337 + CloseableHttpClient httpclient = HttpClients.createDefault();
  338 + url = builderUrl(url, params);
  339 + //请求结果
  340 + String content = "";
  341 + //实例化get方法
  342 + HttpGet httpget = new HttpGet(url);
  343 + if (!CollectionUtils.isEmpty(header)) {
  344 + for (Map.Entry<String, String> entry : header.entrySet()) {
  345 + httpget.setHeader(entry.getKey(), entry.getValue());
  346 + }
  347 + }
  348 +
  349 + try (CloseableHttpResponse response = httpclient.execute(httpget)) {
  350 +
  351 + //执行get方法
  352 + if (response.getStatusLine().getStatusCode() == 200) {
  353 + content = EntityUtils.toString(response.getEntity(), "UTF-8");
  354 + }
  355 + } catch (IOException e) {
  356 + log.error("sendRequest---GET Error!", e);
  357 + }
  358 + return content;
  359 + }
  360 +
  361 + private static String builderUrl(String url, Map<String, String> params) {
  362 + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);
  363 + if (!CollectionUtils.isEmpty(params)) {
  364 + MultiValueMap<String, String> paramsValue = new LinkedMultiValueMap<>();
  365 + for (Map.Entry<String, String> entry : params.entrySet()) {
  366 + paramsValue.add(entry.getKey(), entry.getValue());
  367 + }
  368 +
  369 + uriBuilder = uriBuilder.queryParams(paramsValue);
  370 + }
  371 +
  372 + return uriBuilder.toUriString();
  373 + }
  374 +
  375 + private String sendPost(HttpPost httpPost, String jsonData) {
  376 + CloseableHttpClient httpClient = HttpClients.createDefault();
  377 + StringEntity entity = new StringEntity(jsonData, ContentType.create("application/json", Consts.UTF_8));
  378 + httpPost.setEntity(entity);
  379 + String result = null;
  380 + try {
  381 + CloseableHttpResponse execute = httpClient.execute(httpPost);
  382 + HttpEntity res = execute.getEntity();
  383 + InputStream is = res.getContent();
  384 + int len;
  385 + byte[] buf = new byte[128];
  386 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  387 + while ((len = is.read(buf)) != -1) {
  388 + byteArrayOutputStream.write(buf, 0, len);
  389 + }
  390 + result = byteArrayOutputStream.toString();
  391 + } catch (IOException e) {
  392 + e.printStackTrace();
  393 + }
  394 + return result;
  395 + }
  396 +}
  1 +package com.iot.scheduler.service;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.alibaba.fastjson.TypeReference;
  7 +import com.iot.scheduler.model.DeviceToken;
  8 +import com.iot.scheduler.model.QxDeviceInfo;
  9 +import com.iot.scheduler.model.QxDeviceInfoDetail;
  10 +import jakarta.annotation.Resource;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.apache.commons.lang3.StringUtils;
  13 +import org.apache.http.Consts;
  14 +import org.apache.http.HttpEntity;
  15 +import org.apache.http.client.methods.CloseableHttpResponse;
  16 +import org.apache.http.client.methods.HttpGet;
  17 +import org.apache.http.client.methods.HttpPost;
  18 +import org.apache.http.entity.ContentType;
  19 +import org.apache.http.entity.StringEntity;
  20 +import org.apache.http.impl.client.CloseableHttpClient;
  21 +import org.apache.http.impl.client.HttpClients;
  22 +import org.apache.http.message.BasicHeader;
  23 +import org.apache.http.util.EntityUtils;
  24 +import org.springframework.beans.factory.annotation.Value;
  25 +import org.springframework.data.redis.core.RedisTemplate;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.util.CollectionUtils;
  28 +import org.springframework.util.LinkedMultiValueMap;
  29 +import org.springframework.util.MultiValueMap;
  30 +import org.springframework.web.util.UriComponentsBuilder;
  31 +
  32 +import java.io.ByteArrayOutputStream;
  33 +import java.io.IOException;
  34 +import java.io.InputStream;
  35 +import java.text.SimpleDateFormat;
  36 +import java.util.*;
  37 +import java.util.concurrent.TimeUnit;
  38 +
  39 +/**
  40 + * 安徽亚芯微电子有限公司应用数据同步
  41 + */
  42 +@Slf4j
  43 +@Service
  44 +public class YxwDevicePullService {
  45 +
  46 + @Value("${yxw.iot.organizeId:}")
  47 + private String iotOrganizeId;
  48 + @Value("${yxw.iot.profileId}")
  49 + private String iotProfileId;
  50 + @Value("${yxw.iot.deviceProfileId}")
  51 + private String iotDeviceProfileId;
  52 + @Value("${yxw.iot.userName:}")
  53 + private String iotUserName;
  54 + @Value("${yxw.iot.password:}")
  55 + private String iotPassword;
  56 + @Value("${yxw.iot.tokenUrl}")
  57 + private String iotTokenUrl;
  58 + @Value("${yxw.iot.infoUrl}")
  59 + private String iotDeviceInfoUrl;
  60 + @Value("${yxw.iot.detailUrl}")
  61 + private String iotDeviceDetailUrl;
  62 +
  63 + @Value("${device.token.url}")
  64 + private String deviceTokenUrl;
  65 + @Value("${device.token.userName}")
  66 + private String deviceUserName;
  67 + @Value("${device.token.password}")
  68 + private String devicePassword;
  69 + @Value("${device.info.url}")
  70 + private String deviceInfoUrl;
  71 + @Value("${device.detail.url}")
  72 + private String deviceDetailUrl;
  73 +
  74 + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  75 +
  76 + @Resource
  77 + private RedisTemplate<String, String> redisTemplate;
  78 +
  79 + public void pullDeviceAndPushToIot() {
  80 + String deviceResult = getDeviceInfo();
  81 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  82 + });
  83 +
  84 + JSONArray deviceInfoList = (JSONArray) deviceInfos.get("data");
  85 + List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>();
  86 + List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>();
  87 + Map<String, QxDeviceInfoDetail> qxDeviceInfoDetailMap = new HashMap<>();
  88 + for (Object o : deviceInfoList) {
  89 + JSONObject deviceInfoJson = (JSONObject) o;
  90 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  91 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  92 + qxDeviceInfo.setTransportType("DEFAULT");
  93 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  94 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  95 + qxDeviceInfo.setProfileId(iotProfileId);
  96 +// //项目状态(1:在线,2:离线,3:报警)
  97 +// Integer projectState = deviceInfoJson.getInteger("projectState");
  98 +// if (projectState != null) {
  99 +// qxDeviceInfo.setDescription(String.valueOf(projectState));
  100 +// }
  101 +
  102 + //项目类型
  103 + qxDeviceInfo.setLabel("生产设备");
  104 + //设备名称
  105 + String deviceName = deviceInfoJson.getString("deviceName");
  106 +
  107 + qxDeviceInfo.setName(deviceName);
  108 + qxDeviceInfo.setBrand(deviceName);
  109 + //序列号
  110 + String dtuSn = deviceInfoJson.getString("dtuSn");
  111 + qxDeviceInfo.setSn(dtuSn);
  112 +
  113 + DeviceToken deviceToken = new DeviceToken();
  114 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  115 + deviceToken.setCredentialsId(dtuSn);
  116 + deviceToken.setCredentialsValue(dtuSn);
  117 + qxDeviceInfo.setDeviceToken(deviceToken);
  118 + qxDeviceInfos.add(qxDeviceInfo);
  119 + //有序列号直接获取灯信息
  120 + if (StringUtils.isNotBlank(dtuSn)) {
  121 + String deviceInfoDetails = getDeviceInfoDetail(dtuSn);
  122 + if (StringUtils.isBlank(deviceInfoDetails)) {
  123 + continue;
  124 + }
  125 +
  126 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetails, new TypeReference<>() {
  127 + });
  128 +
  129 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  130 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  131 + continue;
  132 + }
  133 +
  134 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  135 + //灯详情数据
  136 + //序列号
  137 + String dtuSnDetail = deviceInfoDetailJson.getString("dtuSn");
  138 + //开始时间
  139 + String startTime = deviceInfoDetailJson.getString("startTime");
  140 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  141 + qxDeviceInfoDetail.setAlarm(0);
  142 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  143 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  144 + switch (lampState) {
  145 + case 0:
  146 + qxDeviceInfoDetail.setStatus("OFF");
  147 + break;
  148 + case 1:
  149 + qxDeviceInfoDetail.setStatus("ERROR");
  150 + qxDeviceInfoDetail.setAlarm(1);
  151 + break;
  152 + case 2:
  153 + qxDeviceInfoDetail.setStatus("STAND");
  154 + break;
  155 + case 3:
  156 + qxDeviceInfoDetail.setStatus("RUN");
  157 + break;
  158 + default:
  159 + continue;
  160 + }
  161 +
  162 + if (StringUtils.isNotBlank(startTime)) {
  163 + try {
  164 + qxDeviceInfoDetail.setStartTime(dateFormat.parse(startTime));
  165 + } catch (Exception e) {
  166 + log.error("时间格式出错");
  167 + qxDeviceInfoDetail.setStartTime(new Date());
  168 + }
  169 + } else {
  170 + qxDeviceInfoDetail.setStartTime(new Date());
  171 + }
  172 +
  173 + qxDeviceInfoDetail.setDtuSn(dtuSn);
  174 + qxDeviceInfoDetailMap.put(dtuSn, qxDeviceInfoDetail);
  175 + qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
  176 + }
  177 + }
  178 +
  179 + //将数据同步到IOT平台
  180 + Map<String, String> qxParam = new HashMap<>(2);
  181 + qxParam.put("username", iotUserName);
  182 + qxParam.put("password", iotPassword);
  183 +
  184 + HttpPost qxHttpPost = new HttpPost(iotTokenUrl);
  185 + String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam));
  186 + if (StringUtils.isBlank(qxResult)) {
  187 + return;
  188 + }
  189 + Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {
  190 + });
  191 +
  192 + String qxAccessToken = (String) qxRes.get("token");
  193 + if (StringUtils.isBlank(qxAccessToken)) {
  194 + return;
  195 + }
  196 +
  197 + BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken);
  198 + if (!CollectionUtils.isEmpty(qxDeviceInfos)) {
  199 + HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl);
  200 + qxDeviceInfoPost.addHeader(qxAuthorization);
  201 + for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) {
  202 + // todo
  203 + String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));
  204 + //log.info("同步设备信息 syncDeviceInfo:{}", syncDeviceInfo);
  205 + }
  206 + }
  207 +
  208 + if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) {
  209 + for (QxDeviceInfoDetail qxDeviceInfoDetail : qxAddDeviceInfoDetails) {
  210 + String qxDeviceInfoDetailUrlStr = iotDeviceDetailUrl + qxDeviceInfoDetail.getDtuSn() + "/telemetry";
  211 + HttpPost qxDeviceInfoDetailPost = new HttpPost(qxDeviceInfoDetailUrlStr);
  212 + qxDeviceInfoDetailPost.addHeader(qxAuthorization);
  213 + String syncDeviceInfoDetail = sendPost(qxDeviceInfoDetailPost, JSON.toJSONString(qxDeviceInfoDetail));
  214 + }
  215 + }
  216 + }
  217 +
  218 + public String getDeviceInfoDetail(String dtuSn) {
  219 + String accessToken = getAccessToken();
  220 + Map<String, String> dtuSnOb = new HashMap<>(1);
  221 + dtuSnOb.put("dtuSn", dtuSn);
  222 + Map<String, String> headerMap = new HashMap<>(1);
  223 + headerMap.put("Authorization", "Bearer " + accessToken);
  224 + String deviceInfoDetail = sendRequestGet(deviceDetailUrl, dtuSnOb, headerMap);
  225 + if (StringUtils.isBlank(deviceInfoDetail)) {
  226 + return null;
  227 + }
  228 +
  229 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetail,
  230 + new TypeReference<>() {
  231 + });
  232 + Integer deviceInfoDetailCode = (Integer) deviceInfoDetailMap.get("code");
  233 + if (deviceInfoDetailCode != 200) {
  234 + return null;
  235 + }
  236 +
  237 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  238 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  239 + return null;
  240 + }
  241 +
  242 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  243 + //灯详情数据
  244 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  245 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  246 + if (lampState == null) {
  247 + return null;
  248 + }
  249 +
  250 + return deviceInfoDetail;
  251 + }
  252 +
  253 + public String getDeviceInfo() {
  254 + String accessToken = getAccessToken();
  255 + // 初始化headerMap并设置Authorization
  256 + Map<String, String> headerMap = new HashMap<>(1);
  257 + headerMap.put("Authorization", "Bearer " + accessToken);
  258 +
  259 + Map<String, String> paramsMap = new HashMap<>();
  260 + paramsMap.put("groupName", "安徽亚芯微电子有限公司");
  261 +
  262 + // 第一次请求设备信息
  263 + String deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  264 +
  265 + // 检查设备信息是否为空
  266 + if (StringUtils.isBlank(deviceResult)) {
  267 + return null;
  268 + }
  269 +
  270 + // 解析设备信息
  271 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  272 + });
  273 + Integer deviceInfoCode = (Integer) deviceInfos.get("code");
  274 +
  275 + // 如果code不为200,可能是accessToken失效,重新获取token并重试
  276 + if (deviceInfoCode != 200) {
  277 + accessToken = getAccessToken();
  278 + if (StringUtils.isEmpty(accessToken)) {
  279 + return null;
  280 + }
  281 +
  282 + // 更新headerMap中的Authorization
  283 + headerMap.put("Authorization", "Bearer " + accessToken);
  284 +
  285 + // 第二次请求设备信息
  286 + deviceResult = sendRequestGet(deviceInfoUrl, paramsMap, headerMap);
  287 + if (StringUtils.isBlank(deviceResult)) {
  288 + return null;
  289 + }
  290 +
  291 + // 重新解析设备信息
  292 + deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {
  293 + });
  294 + deviceInfoCode = (Integer) deviceInfos.get("code");
  295 +
  296 + // 如果第二次请求仍然失败,返回错误信息
  297 + if (deviceInfoCode != 200) {
  298 + return null;
  299 + }
  300 + }
  301 +
  302 + // 返回成功的设备信息
  303 + return deviceResult;
  304 + }
  305 +
  306 + private String getAccessToken() {
  307 + String accessToken = "";
  308 + String redisKey = "device_token";
  309 + if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(redisKey)) && redisTemplate.getExpire(redisKey) > 0) {
  310 + return redisTemplate.opsForValue().get(redisKey);
  311 + }
  312 +
  313 + Map<String, String> param = new HashMap<>(2);
  314 + param.put("username", deviceUserName);
  315 + param.put("password", devicePassword);
  316 + HttpPost httpPost = new HttpPost(deviceTokenUrl);
  317 + String result = sendPost(httpPost, JSON.toJSONString(param));
  318 + if (StringUtils.isBlank(result)) {
  319 + return accessToken;
  320 + }
  321 +
  322 + Map<String, Object> res = JSON.parseObject(result, new TypeReference<>() {
  323 + });
  324 +
  325 + Integer code = (Integer) res.get("code");
  326 + if (code == 200) {
  327 + JSONObject data = (JSONObject) res.get("data");
  328 + accessToken = (String) data.get("token");
  329 + redisTemplate.opsForValue().set(redisKey, accessToken, 3600, TimeUnit.SECONDS); // 一小时过期
  330 + }
  331 +
  332 + return accessToken;
  333 + }
  334 +
  335 + public static String sendRequestGet(String url, Map<String, String> params, Map<String, String> header) {
  336 + //实例化httpclient
  337 + CloseableHttpClient httpclient = HttpClients.createDefault();
  338 + url = builderUrl(url, params);
  339 + //请求结果
  340 + String content = "";
  341 + //实例化get方法
  342 + HttpGet httpget = new HttpGet(url);
  343 + if (!CollectionUtils.isEmpty(header)) {
  344 + for (Map.Entry<String, String> entry : header.entrySet()) {
  345 + httpget.setHeader(entry.getKey(), entry.getValue());
  346 + }
  347 + }
  348 +
  349 + try (CloseableHttpResponse response = httpclient.execute(httpget)) {
  350 +
  351 + //执行get方法
  352 + if (response.getStatusLine().getStatusCode() == 200) {
  353 + content = EntityUtils.toString(response.getEntity(), "UTF-8");
  354 + }
  355 + } catch (IOException e) {
  356 + log.error("sendRequest---GET Error!", e);
  357 + }
  358 + return content;
  359 + }
  360 +
  361 + private static String builderUrl(String url, Map<String, String> params) {
  362 + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);
  363 + if (!CollectionUtils.isEmpty(params)) {
  364 + MultiValueMap<String, String> paramsValue = new LinkedMultiValueMap<>();
  365 + for (Map.Entry<String, String> entry : params.entrySet()) {
  366 + paramsValue.add(entry.getKey(), entry.getValue());
  367 + }
  368 +
  369 + uriBuilder = uriBuilder.queryParams(paramsValue);
  370 + }
  371 +
  372 + return uriBuilder.toUriString();
  373 + }
  374 +
  375 + private String sendPost(HttpPost httpPost, String jsonData) {
  376 + CloseableHttpClient httpClient = HttpClients.createDefault();
  377 + StringEntity entity = new StringEntity(jsonData, ContentType.create("application/json", Consts.UTF_8));
  378 + httpPost.setEntity(entity);
  379 + String result = null;
  380 + try {
  381 + CloseableHttpResponse execute = httpClient.execute(httpPost);
  382 + HttpEntity res = execute.getEntity();
  383 + InputStream is = res.getContent();
  384 + int len;
  385 + byte[] buf = new byte[128];
  386 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  387 + while ((len = is.read(buf)) != -1) {
  388 + byteArrayOutputStream.write(buf, 0, len);
  389 + }
  390 + result = byteArrayOutputStream.toString();
  391 + } catch (IOException e) {
  392 + e.printStackTrace();
  393 + }
  394 + return result;
  395 + }
  396 +}
  1 +package com.iot.scheduler.utils;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +
  5 +import java.sql.*;
  6 +
  7 +@Slf4j
  8 +public class SqlTypedValueUtils {
  9 +
  10 + public static Object getTypedValue(ResultSet rs, int index, int sqlType) throws SQLException {
  11 + Object value;
  12 +
  13 + try {
  14 + switch (sqlType) {
  15 + case Types.BIT:
  16 + case Types.BOOLEAN:
  17 + value = rs.getBoolean(index);
  18 + return rs.wasNull() ? null : value;
  19 +
  20 + case Types.TINYINT:
  21 + case Types.SMALLINT:
  22 + case Types.INTEGER:
  23 + value = rs.getInt(index);
  24 + return rs.wasNull() ? null : value;
  25 +
  26 + case Types.BIGINT:
  27 + value = rs.getLong(index);
  28 + return rs.wasNull() ? null : value;
  29 +
  30 + case Types.FLOAT:
  31 + case Types.REAL:
  32 + value = rs.getFloat(index);
  33 + return rs.wasNull() ? null : value;
  34 +
  35 + case Types.DOUBLE:
  36 + value = rs.getDouble(index);
  37 + return rs.wasNull() ? null : value;
  38 +
  39 + case Types.NUMERIC:
  40 + case Types.DECIMAL:
  41 + value = rs.getBigDecimal(index);
  42 + return rs.wasNull() ? null : value;
  43 +
  44 + case Types.CHAR:
  45 + case Types.VARCHAR:
  46 + case Types.LONGVARCHAR:
  47 + case Types.NCHAR:
  48 + case Types.NVARCHAR:
  49 + case Types.LONGNVARCHAR:
  50 + value = rs.getString(index);
  51 + return rs.wasNull() ? null : value;
  52 +
  53 + case Types.DATE:
  54 + Date date = rs.getDate(index);
  55 + return date != null ? date.toLocalDate() : null;
  56 +
  57 + case Types.TIME:
  58 + Time time = rs.getTime(index);
  59 + return time != null ? time.toLocalTime() : null;
  60 +
  61 + case Types.TIMESTAMP:
  62 + Timestamp timestamp = rs.getTimestamp(index);
  63 + return timestamp != null ? timestamp.toLocalDateTime() : null;
  64 +
  65 + case Types.BINARY:
  66 + case Types.VARBINARY:
  67 + case Types.LONGVARBINARY:
  68 + value = rs.getBytes(index);
  69 + return rs.wasNull() ? null : value;
  70 +
  71 + case Types.BLOB:
  72 + value = rs.getBlob(index);
  73 + return rs.wasNull() ? null : value;
  74 +
  75 + case Types.CLOB:
  76 + value = rs.getClob(index);
  77 + return rs.wasNull() ? null : value;
  78 +
  79 + default:
  80 + value = rs.getObject(index);
  81 + return rs.wasNull() ? null : value;
  82 + }
  83 + } catch (SQLException e) {
  84 + log.error("获取结果集第{}列数据时发生异常,数据类型: {}", index, sqlType, e);
  85 + throw e;
  86 + }
  87 + }
  88 +}
src/main/java/com/iot/scheduler/zone/CdZoneScheduler.java renamed from src/main/java/com/iot/scheduler/zone/ChizhouZoneScheduler.java
1 package com.iot.scheduler.zone; 1 package com.iot.scheduler.zone;
2 2
  3 +import com.iot.scheduler.service.CdDevicePullService;
3 import com.iot.scheduler.task.AbstractZoneScheduler; 4 import com.iot.scheduler.task.AbstractZoneScheduler;
  5 +import jakarta.annotation.Resource;
4 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
5 import org.springframework.scheduling.annotation.Scheduled; 7 import org.springframework.scheduling.annotation.Scheduled;
6 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
7 9
8 @Slf4j 10 @Slf4j
9 @Component 11 @Component
10 -public class ChizhouZoneScheduler extends AbstractZoneScheduler { 12 +public class CdZoneScheduler extends AbstractZoneScheduler {
  13 +
  14 + @Resource
  15 + private CdDevicePullService cdDevicePullService;
11 16
12 @Override 17 @Override
13 protected String getZoneName() { 18 protected String getZoneName() {
14 - return "Chizhou (池州经开区)"; 19 + return "CD (恩博力)";
15 } 20 }
16 21
17 - @Scheduled(cron = "${scheduler.chizhou.pull:0 0/10 * * * ?}") 22 + @Scheduled(cron = "${scheduler.cd.pull:0 0/10 * * * ?}")
18 public void pullDevicesFromThirdParty() { 23 public void pullDevicesFromThirdParty() {
19 String taskName = "Pull Devices (3rd Party -> IoT)"; 24 String taskName = "Pull Devices (3rd Party -> IoT)";
20 logStart(taskName); 25 logStart(taskName);
21 try { 26 try {
22 - // TODO: Implement actual logic  
23 log.info("[{}] Simulating pulling devices...", getZoneName()); 27 log.info("[{}] Simulating pulling devices...", getZoneName());
24 - Thread.sleep(1000);  
25 - } catch (Exception e) {  
26 - logError(taskName, e);  
27 - } finally {  
28 - logEnd(taskName);  
29 - }  
30 - }  
31 -  
32 - @Scheduled(cron = "${scheduler.chizhou.push:0 0/15 * * * ?}")  
33 - public void pushDevicesToThirdParty() {  
34 - String taskName = "Push Devices (IoT -> 3rd Party)";  
35 - logStart(taskName);  
36 - try {  
37 - // TODO: Implement actual logic  
38 - log.info("[{}] Simulating pushing devices...", getZoneName()); 28 + cdDevicePullService.pullDeviceAndPushToIot();
39 Thread.sleep(1000); 29 Thread.sleep(1000);
40 } catch (Exception e) { 30 } catch (Exception e) {
41 logError(taskName, e); 31 logError(taskName, e);
  1 +package com.iot.scheduler.zone;
  2 +
  3 +import com.iot.scheduler.service.EblDevicePullService;
  4 +import com.iot.scheduler.task.AbstractZoneScheduler;
  5 +import jakarta.annotation.Resource;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.scheduling.annotation.Scheduled;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +@Slf4j
  11 +@Component
  12 +public class EblZoneScheduler extends AbstractZoneScheduler {
  13 +
  14 + @Resource
  15 + private EblDevicePullService eblDevicePullService;
  16 +
  17 + @Override
  18 + protected String getZoneName() {
  19 + return "EBL (恩博力)";
  20 + }
  21 +
  22 + @Scheduled(cron = "${scheduler.ebl.pull:0 0/10 * * * ?}")
  23 + public void pullDevicesFromThirdParty() {
  24 + String taskName = "Pull Devices (3rd Party -> IoT)";
  25 + logStart(taskName);
  26 + try {
  27 + log.info("[{}] Simulating pulling devices...", getZoneName());
  28 + eblDevicePullService.pullDeviceAndPushToIot();
  29 + Thread.sleep(1000);
  30 + } catch (Exception e) {
  31 + logError(taskName, e);
  32 + } finally {
  33 + logEnd(taskName);
  34 + }
  35 + }
  36 +}
  1 +package com.iot.scheduler.zone;
  2 +
  3 +import com.iot.scheduler.service.TwgdDevicePullService;
  4 +import com.iot.scheduler.task.AbstractZoneScheduler;
  5 +import jakarta.annotation.Resource;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.scheduling.annotation.Scheduled;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +@Slf4j
  11 +@Component
  12 +public class TwgdZoneScheduler extends AbstractZoneScheduler {
  13 +
  14 + @Resource
  15 + private TwgdDevicePullService twgdDevicePullService;
  16 +
  17 + @Override
  18 + protected String getZoneName() {
  19 + return "TWGD (拓维光电)";
  20 + }
  21 +
  22 + @Scheduled(cron = "${scheduler.twgd.pull:0 0/10 * * * ?}")
  23 + public void pullDevicesFromThirdParty() {
  24 + String taskName = "Pull Devices (3rd Party -> IoT)";
  25 + logStart(taskName);
  26 + try {
  27 + log.info("[{}] Simulating pulling devices...", getZoneName());
  28 + twgdDevicePullService.pullDeviceAndPushToIot();
  29 + Thread.sleep(1000);
  30 + } catch (Exception e) {
  31 + logError(taskName, e);
  32 + } finally {
  33 + logEnd(taskName);
  34 + }
  35 + }
  36 +}
  1 +package com.iot.scheduler.zone;
  2 +
  3 +import com.iot.scheduler.service.YxwDevicePullService;
  4 +import com.iot.scheduler.task.AbstractZoneScheduler;
  5 +import jakarta.annotation.Resource;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.scheduling.annotation.Scheduled;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +@Slf4j
  11 +@Component
  12 +public class YxwZoneScheduler extends AbstractZoneScheduler {
  13 +
  14 + @Resource
  15 + private YxwDevicePullService yxwDevicePullService;
  16 +
  17 + @Override
  18 + protected String getZoneName() {
  19 + return "YXW (亚芯微)";
  20 + }
  21 +
  22 + @Scheduled(cron = "${scheduler.yxw.pull:0 0/10 * * * ?}")
  23 + public void pullDevicesFromThirdParty() {
  24 + String taskName = "Pull Devices (3rd Party -> IoT)";
  25 + logStart(taskName);
  26 + try {
  27 + log.info("[{}] Simulating pulling devices...", getZoneName());
  28 + yxwDevicePullService.pullDeviceAndPushToIot();
  29 + Thread.sleep(1000);
  30 + } catch (Exception e) {
  31 + logError(taskName, e);
  32 + } finally {
  33 + logEnd(taskName);
  34 + }
  35 + }
  36 +}
@@ -3,9 +3,20 @@ spring: @@ -3,9 +3,20 @@ spring:
3 name: iot-scheduler 3 name: iot-scheduler
4 main: 4 main:
5 banner-mode: off 5 banner-mode: off
  6 + data:
  7 + redis:
  8 + host: 127.0.0.1
  9 + port: 6379
  10 + # 如果有密码,取消注释并设置
  11 + # password: your_password
  12 + # 数据库索引,默认为0
  13 + database: 0
  14 + # 连接超时时间(毫秒)
  15 + connect-timeout: 5000
  16 + timeout: 5000
6 17
7 server: 18 server:
8 - port: 8080 19 + port: 33221
9 20
10 logging: 21 logging:
11 level: 22 level:
@@ -18,9 +29,71 @@ scheduler: @@ -18,9 +29,71 @@ scheduler:
18 huaining: 29 huaining:
19 pull: "0 0/5 * * * ?" # Every 5 minutes 30 pull: "0 0/5 * * * ?" # Every 5 minutes
20 push: "0 0/10 * * * ?" # Every 10 minutes 31 push: "0 0/10 * * * ?" # Every 10 minutes
21 - chizhou: 32 + yxw:
22 pull: "0 0/5 * * * ?" 33 pull: "0 0/5 * * * ?"
23 push: "0 0/10 * * * ?" 34 push: "0 0/10 * * * ?"
24 panji: 35 panji:
25 pull: "0 0/5 * * * ?" 36 pull: "0 0/5 * * * ?"
26 push: "0 0/10 * * * ?" 37 push: "0 0/10 * * * ?"
  38 + ebl:
  39 + pull: "0 0/5 * * * ?"
  40 + push: "0 0/10 * * * ?"
  41 + cd:
  42 + pull: "0 0/5 * * * ?"
  43 + push: "0 0/10 * * * ?"
  44 + twgd:
  45 + pull: "0 0/5 * * * ?"
  46 + push: "0 0/10 * * * ?"
  47 +yxw:
  48 + iot:
  49 + organizeId: "7f6a3af7-77e4-456b-93e0-ef0437657e3d"
  50 + profileId: "f38f35f0-20e3-11f1-8e7c-372a03581f6c"
  51 + deviceProfileId: "f38f35f0-20e3-11f1-8e7c-372a03581f6c"
  52 + userName: "yxw"
  53 + password: "Yxw@123.com"
  54 + tokenUrl: "http://192.168.0.189:8080/api/auth/login"
  55 + infoUrl: "http://192.168.0.189:8080/api/yt/device"
  56 + detailUrl: "http://192.168.0.189:8080/api/v1/"
  57 +
  58 +ebl:
  59 + iot:
  60 + organizeId: "06620d16-4492-457e-b035-44b31c6dec09"
  61 + profileId: "836c8bb0-20e3-11f1-8e7c-372a03581f6c"
  62 + deviceProfileId: "836c8bb0-20e3-11f1-8e7c-372a03581f6c"
  63 + userName: "ebl"
  64 + password: "Ebl@123.com"
  65 + tokenUrl: "http://192.168.0.189:8080/api/auth/login"
  66 + infoUrl: "http://192.168.0.189:8080/api/yt/device"
  67 + detailUrl: "http://192.168.0.189:8080/api/v1/"
  68 +
  69 +cd:
  70 + iot:
  71 + organizeId: "8cae4f47-6fe1-451f-be66-2452f2ed8bfd"
  72 + profileId: "075d4700-20e1-11f1-8e7c-372a03581f6c"
  73 + deviceProfileId: "075d4700-20e1-11f1-8e7c-372a03581f6c"
  74 + userName: "cd"
  75 + password: "Cd@123.com"
  76 + tokenUrl: "http://192.168.0.189:8080/api/auth/login"
  77 + infoUrl: "http://192.168.0.189:8080/api/yt/device"
  78 + detailUrl: "http://192.168.0.189:8080/api/v1/"
  79 +
  80 +twgd:
  81 + iot:
  82 + organizeId: "bfc75fef-8139-4509-b3c3-ae8397476a22"
  83 + profileId: "a29a67e0-20df-11f1-8e7c-372a03581f6c"
  84 + deviceProfileId: "a29a67e0-20df-11f1-8e7c-372a03581f6c"
  85 + userName: "twgd"
  86 + password: "Twgd@123.com"
  87 + tokenUrl: "http://192.168.0.189:8080/api/auth/login"
  88 + infoUrl: "http://192.168.0.189:8080/api/yt/device"
  89 + detailUrl: "http://192.168.0.189:8080/api/v1/"
  90 +
  91 +device:
  92 + token:
  93 + url: "https://iotgc.cniot.vip/auth/token"
  94 + userName: "chuzhoult"
  95 + password: "111111"
  96 + info:
  97 + url: "https://iotgc.cniot.vip/triColorLamp/userGroupDtuSns"
  98 + detail:
  99 + url: "https://iotgc.cniot.vip/triColorLamp/dtuSnState"