Commit 692d58d5bcd89999d35db0f6d5bc9f6db31dad9d

Authored by 杨鸣坤
1 parent d9d0e0b6

feat: 支持本地模拟设备数据同步

@@ -76,107 +76,187 @@ public class BjkjDevicePullService { @@ -76,107 +76,187 @@ public class BjkjDevicePullService {
76 @Resource 76 @Resource
77 private RedisTemplate<String, String> redisTemplate; 77 private RedisTemplate<String, String> redisTemplate;
78 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"); 79 + /**
  80 + * 设备同步主方法
  81 + * @param useRemoteData true: 从远程接口获取设备数据; false: 使用本地设备列表
  82 + */
  83 + public void pullDeviceAndPushToIot(boolean useRemoteData) {
85 List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>(); 84 List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>();
86 List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>(); 85 List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>();
87 Map<String, QxDeviceInfoDetail> qxDeviceInfoDetailMap = new HashMap<>(); 86 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 87
126 - Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetails, new TypeReference<>() {  
127 - }); 88 + if (useRemoteData) {
  89 + // 从远程接口获取设备数据
  90 + String deviceResult = getDeviceInfo();
  91 + if (StringUtils.isBlank(deviceResult)) {
  92 + log.error("获取远程设备信息失败");
  93 + return;
  94 + }
128 95
129 - JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");  
130 - if (CollectionUtils.isEmpty(deviceInfoDetailList)) {  
131 - continue;  
132 - } 96 + Map<String, Object> deviceInfos = JSON.parseObject(deviceResult, new TypeReference<>() {});
  97 + JSONArray deviceInfoList = (JSONArray) deviceInfos.get("data");
  98 +
  99 + for (Object o : deviceInfoList) {
  100 + JSONObject deviceInfoJson = (JSONObject) o;
  101 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  102 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  103 + qxDeviceInfo.setTransportType("DEFAULT");
  104 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  105 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  106 + qxDeviceInfo.setProfileId(iotProfileId);
  107 + qxDeviceInfo.setLabel("生产设备");
  108 +
  109 + //设备名称
  110 + String deviceName = deviceInfoJson.getString("deviceName");
  111 + qxDeviceInfo.setName(deviceName);
  112 + qxDeviceInfo.setBrand(deviceName);
133 113
134 - JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);  
135 - //灯详情数据  
136 //序列号 114 //序列号
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: 115 + String dtuSn = deviceInfoJson.getString("dtuSn");
  116 + qxDeviceInfo.setSn(dtuSn);
  117 +
  118 + DeviceToken deviceToken = new DeviceToken();
  119 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  120 + deviceToken.setCredentialsId(dtuSn);
  121 + deviceToken.setCredentialsValue(dtuSn);
  122 + qxDeviceInfo.setDeviceToken(deviceToken);
  123 + qxDeviceInfos.add(qxDeviceInfo);
  124 +
  125 + //有序列号直接获取灯信息
  126 + if (StringUtils.isNotBlank(dtuSn)) {
  127 + String deviceInfoDetails = getDeviceInfoDetail(dtuSn);
  128 + if (StringUtils.isBlank(deviceInfoDetails)) {
159 continue; 129 continue;
160 - } 130 + }
  131 +
  132 + Map<String, Object> deviceInfoDetailMap = JSON.parseObject(deviceInfoDetails, new TypeReference<>() {});
  133 + JSONArray deviceInfoDetailList = (JSONArray) deviceInfoDetailMap.get("data");
  134 + if (CollectionUtils.isEmpty(deviceInfoDetailList)) {
  135 + continue;
  136 + }
161 137
162 - if (StringUtils.isNotBlank(startTime)) {  
163 - try {  
164 - qxDeviceInfoDetail.setStartTime(dateFormat.parse(startTime));  
165 - } catch (Exception e) {  
166 - log.error("时间格式出错"); 138 + JSONObject deviceInfoDetailJson = (JSONObject) deviceInfoDetailList.get(0);
  139 + //灯详情数据
  140 + //序列号
  141 + String dtuSnDetail = deviceInfoDetailJson.getString("dtuSn");
  142 + //开始时间
  143 + String startTime = deviceInfoDetailJson.getString("startTime");
  144 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  145 + qxDeviceInfoDetail.setAlarm(0);
  146 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  147 + Integer lampState = deviceInfoDetailJson.getInteger("lampState");
  148 + switch (lampState) {
  149 + case 0:
  150 + qxDeviceInfoDetail.setStatus("OFF");
  151 + break;
  152 + case 1:
  153 + qxDeviceInfoDetail.setStatus("ERROR");
  154 + qxDeviceInfoDetail.setAlarm(1);
  155 + break;
  156 + case 2:
  157 + qxDeviceInfoDetail.setStatus("STAND");
  158 + break;
  159 + case 3:
  160 + qxDeviceInfoDetail.setStatus("RUN");
  161 + break;
  162 + default:
  163 + continue;
  164 + }
  165 +
  166 + if (StringUtils.isNotBlank(startTime)) {
  167 + try {
  168 + qxDeviceInfoDetail.setStartTime(dateFormat.parse(startTime));
  169 + } catch (Exception e) {
  170 + log.error("时间格式出错");
  171 + qxDeviceInfoDetail.setStartTime(new Date());
  172 + }
  173 + } else {
167 qxDeviceInfoDetail.setStartTime(new Date()); 174 qxDeviceInfoDetail.setStartTime(new Date());
168 } 175 }
169 - } else {  
170 - qxDeviceInfoDetail.setStartTime(new Date()); 176 +
  177 + qxDeviceInfoDetail.setDtuSn(dtuSn);
  178 + qxDeviceInfoDetailMap.put(dtuSn, qxDeviceInfoDetail);
  179 + qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
171 } 180 }
  181 + }
  182 + } else {
  183 + // 使用本地设备列表
  184 + List<String> deviceNameList = getDeviceNameList();
  185 + int totalDevices = deviceNameList.size();
  186 +
  187 + // 按照 8:1:1 的比例分配状态
  188 + int runCount = (int) Math.round(totalDevices * 0.8);
  189 + int standCount = (int) Math.round(totalDevices * 0.1);
  190 + int offCount = totalDevices - runCount - standCount;
  191 +
  192 + // 创建状态列表
  193 + List<String> statusList = new ArrayList<>();
  194 + for (int i = 0; i < runCount; i++) {
  195 + statusList.add("RUN");
  196 + }
  197 + for (int i = 0; i < standCount; i++) {
  198 + statusList.add("STAND");
  199 + }
  200 + for (int i = 0; i < offCount; i++) {
  201 + statusList.add("OFF");
  202 + }
172 203
173 - qxDeviceInfoDetail.setDtuSn(dtuSn);  
174 - qxDeviceInfoDetailMap.put(dtuSn, qxDeviceInfoDetail); 204 + // 打乱状态顺序,使设备状态随机分布
  205 + Collections.shuffle(statusList);
  206 +
  207 + // 获取当前日期作为序列号前缀
  208 + String datePrefix = "BJKJ20260401";
  209 +
  210 + for (int i = 0; i < totalDevices; i++) {
  211 + String deviceName = deviceNameList.get(i);
  212 + String status = statusList.get(i);
  213 +
  214 + // 生成序列号:BJKJ20260401 + 三位数序列号(从001开始)
  215 + String serialNumber = datePrefix + String.format("%03d", (i + 1));
  216 +
  217 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  218 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  219 + qxDeviceInfo.setTransportType("DEFAULT");
  220 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  221 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  222 + qxDeviceInfo.setProfileId(iotProfileId);
  223 + qxDeviceInfo.setLabel("生产设备");
  224 + qxDeviceInfo.setName(deviceName);
  225 + qxDeviceInfo.setBrand(deviceName);
  226 + qxDeviceInfo.setSn(serialNumber);
  227 +
  228 + DeviceToken deviceToken = new DeviceToken();
  229 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  230 + deviceToken.setCredentialsId(serialNumber);
  231 + deviceToken.setCredentialsValue(serialNumber);
  232 + qxDeviceInfo.setDeviceToken(deviceToken);
  233 + qxDeviceInfos.add(qxDeviceInfo);
  234 +
  235 + // 创建设备详情(遥测数据)
  236 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  237 + qxDeviceInfoDetail.setAlarm(0);
  238 + qxDeviceInfoDetail.setStatus(status);
  239 + qxDeviceInfoDetail.setStartTime(new Date());
  240 + qxDeviceInfoDetail.setDtuSn(serialNumber);
  241 + qxDeviceInfoDetailMap.put(serialNumber, qxDeviceInfoDetail);
175 qxAddDeviceInfoDetails.add(qxDeviceInfoDetail); 242 qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
  243 +
  244 + log.debug("生成设备 - 名称: {}, 序列号: {}, 状态: {}", deviceName, serialNumber, status);
176 } 245 }
  246 +
  247 + log.info("设备状态分配统计 - 总数: {}, RUN: {}, STAND: {}, OFF: {}",
  248 + totalDevices, runCount, standCount, offCount);
177 } 249 }
178 250
179 - //将数据同步到IOT平台 251 + // 上传数据到IoT平台
  252 + uploadToIotPlatform(qxDeviceInfos, qxAddDeviceInfoDetails);
  253 + }
  254 +
  255 + /**
  256 + * 获取IoT平台Token并上传设备数据
  257 + */
  258 + private void uploadToIotPlatform(List<QxDeviceInfo> qxDeviceInfos, List<QxDeviceInfoDetail> qxAddDeviceInfoDetails) {
  259 + // 获取IoT平台Token
180 Map<String, String> qxParam = new HashMap<>(2); 260 Map<String, String> qxParam = new HashMap<>(2);
181 qxParam.put("username", iotUserName); 261 qxParam.put("username", iotUserName);
182 qxParam.put("password", iotPassword); 262 qxParam.put("password", iotPassword);
@@ -184,37 +264,409 @@ public class BjkjDevicePullService { @@ -184,37 +264,409 @@ public class BjkjDevicePullService {
184 HttpPost qxHttpPost = new HttpPost(iotTokenUrl); 264 HttpPost qxHttpPost = new HttpPost(iotTokenUrl);
185 String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam)); 265 String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam));
186 if (StringUtils.isBlank(qxResult)) { 266 if (StringUtils.isBlank(qxResult)) {
  267 + log.error("获取IoT平台Token失败");
187 return; 268 return;
188 } 269 }
189 - Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {  
190 - });  
191 270
  271 + Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {});
192 String qxAccessToken = (String) qxRes.get("token"); 272 String qxAccessToken = (String) qxRes.get("token");
193 if (StringUtils.isBlank(qxAccessToken)) { 273 if (StringUtils.isBlank(qxAccessToken)) {
  274 + log.error("IoT平台Token为空");
194 return; 275 return;
195 } 276 }
196 277
197 BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken); 278 BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken);
  279 +
  280 + // 批量上传设备信息
198 if (!CollectionUtils.isEmpty(qxDeviceInfos)) { 281 if (!CollectionUtils.isEmpty(qxDeviceInfos)) {
199 HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl); 282 HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl);
200 qxDeviceInfoPost.addHeader(qxAuthorization); 283 qxDeviceInfoPost.addHeader(qxAuthorization);
  284 +
  285 + int successCount = 0;
  286 + int failCount = 0;
  287 +
201 for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) { 288 for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) {
202 - // todo  
203 - String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));  
204 - //log.info("同步设备信息 syncDeviceInfo:{}", syncDeviceInfo); 289 + try {
  290 + String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));
  291 +
  292 + if (StringUtils.isNotBlank(syncDeviceInfo)) {
  293 + Map<String, Object> result = JSON.parseObject(syncDeviceInfo, new TypeReference<Map<String, Object>>() {});
  294 + if (result.containsKey("id") || (result.containsKey("success") && (Boolean) result.get("success"))) {
  295 + successCount++;
  296 + log.info("设备上传成功 - 名称: {}, 序列号: {}", qxDeviceInfo.getName(), qxDeviceInfo.getSn());
  297 + } else {
  298 + failCount++;
  299 + log.error("设备上传失败 - 名称: {}, 序列号: {}, 返回: {}",
  300 + qxDeviceInfo.getName(), qxDeviceInfo.getSn(), syncDeviceInfo);
  301 + }
  302 + } else {
  303 + failCount++;
  304 + log.error("设备上传返回为空 - 名称: {}, 序列号: {}", qxDeviceInfo.getName(), qxDeviceInfo.getSn());
  305 + }
  306 + } catch (Exception e) {
  307 + failCount++;
  308 + log.error("设备上传异常 - 名称: {}, 序列号: {}", qxDeviceInfo.getName(), qxDeviceInfo.getSn(), e);
  309 + }
205 } 310 }
  311 +
  312 + log.info("设备上传完成 - 成功: {}, 失败: {}", successCount, failCount);
206 } 313 }
207 314
  315 + // 批量上传设备详情(遥测数据)
208 if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) { 316 if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) {
  317 + int successCount = 0;
  318 + int failCount = 0;
  319 +
209 for (QxDeviceInfoDetail qxDeviceInfoDetail : qxAddDeviceInfoDetails) { 320 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)); 321 + try {
  322 + String qxDeviceInfoDetailUrlStr = iotDeviceDetailUrl + qxDeviceInfoDetail.getDtuSn() + "/telemetry";
  323 + HttpPost qxDeviceInfoDetailPost = new HttpPost(qxDeviceInfoDetailUrlStr);
  324 + qxDeviceInfoDetailPost.addHeader(qxAuthorization);
  325 +
  326 + String syncDeviceInfoDetail = sendPost(qxDeviceInfoDetailPost, JSON.toJSONString(qxDeviceInfoDetail));
  327 + successCount++;
  328 + log.debug("设备详情上传成功 - 序列号: {}, 状态: {}",
  329 + qxDeviceInfoDetail.getDtuSn(), qxDeviceInfoDetail.getStatus());
  330 + } catch (Exception e) {
  331 + failCount++;
  332 + log.error("设备详情上传异常 - 序列号: {}", qxDeviceInfoDetail.getDtuSn(), e);
  333 + }
214 } 334 }
  335 +
  336 + log.info("设备详情上传完成 - 成功: {}, 失败: {}", successCount, failCount);
215 } 337 }
216 } 338 }
217 339
  340 + /**
  341 + * 获取设备名称列表
  342 + */
  343 + private List<String> getDeviceNameList() {
  344 + return Arrays.asList(
  345 + "组装机_1106100002",
  346 + "组装机撕膜检改造_1106100003",
  347 + "自动标签打印机_2213140002",
  348 + "喷码机_1111190002",
  349 + "喷码机皮带线_1301110005",
  350 + "喷码滚轮线_1301100002",
  351 + "FI检查流水线(6M)_1301110003",
  352 + "流水线(9M)_1301110001",
  353 + "自动Tape贴附机_1110180001",
  354 + "客户码及易撕贴贴附机_2213140003",
  355 + "真空打包机_1401110002",
  356 + "AG膜贴膜机_1110170001",
  357 + "贴合线AG贴膜机装机_1110170002",
  358 + "贴合线AG贴膜机装机_1110170003",
  359 + "脱泡机_1110170004",
  360 + "OCR贴合机_1110160001",
  361 + "橱窗式老化炉_1202040001",
  362 + "出货膜贴膜机_1110170002",
  363 + "抽屉式老化炉_1202040004",
  364 + "抽屉式老化炉_1202040005",
  365 + "凌云AOI_1201020002",
  366 + "点灯机_1202070001",
  367 + "点灯机_1202070002",
  368 + "点灯机_1202070003",
  369 + "点灯机_1202070004",
  370 + "点灯机_1202070005",
  371 + "点灯机_1202070006",
  372 + "点灯机_1202070007",
  373 + "点灯机_1202070008",
  374 + "点灯机_1202070009",
  375 + "5点亮度治具_1202080001",
  376 + "OTP治具_1202080004",
  377 + "OTP治具_1202080005",
  378 + "OTP治具_1202080006",
  379 + "OTP治具_1202080007",
  380 + "半自动OCA软对硬贴合机_1110150001",
  381 + "半自动OCA硬对硬贴合机_1110150002",
  382 + "半自动脱泡机_1107110002",
  383 + "2.5次元_1203010002",
  384 + "膜厚测量仪_1203020001",
  385 + "水滴角测试仪_1203030001",
  386 + "条码打印机/型号:斑马105SL 分_2213150001",
  387 + "条码打印机/型号:斑马105SL 分_2213150003",
  388 + "日置数字照度计_1203040001",
  389 + "无尘室专用吸尘器_1401200001",
  390 + "能量计/UV_1203050001",
  391 + "测温仪/日本图技_1203060001",
  392 + "锥入度仪_1203070001",
  393 + "缠膜机_1401180001",
  394 + "玻璃二位蚀刻码扫码治具_2211130001",
  395 + "防爆柜_1401100001",
  396 + "重锤式表面电阻测试仪_1203080001",
  397 + "手持式热熔打包机_1401190001",
  398 + "手持式热熔打包机_1401190002",
  399 + "三坐标_1203090001",
  400 + "背光点胶组装机_1106100004",
  401 + "双联屏AOI_1201020004",
  402 + "显微镜_1203100001",
  403 + "烤箱_1202040006",
  404 + "上板机_1301010001",
  405 + "镭雕机_1101030001",
  406 + "0.8m接驳台_1301030001",
  407 + "印刷机_1102040001",
  408 + "印刷机_1102040002",
  409 + "0.5m接驳台_1301030002",
  410 + "0.5m接驳台_1301030003",
  411 + "移载机_1301080001",
  412 + "0.5m双轨接驳台_1301030004",
  413 + "SPI_1201010001",
  414 + "1.2m双规筛选接驳台_1301030005",
  415 + "1.2m双规接驳台_1301030006",
  416 + "贴片机_1101010001",
  417 + "贴片机_1101010002",
  418 + "贴片机_1101010003",
  419 + "贴片机_1101010004",
  420 + "0.5m双轨接驳台_1301030007",
  421 + "0.5m移载机_1301080002",
  422 + "1m接驳台_1301030008",
  423 + "转角机_1301030001",
  424 + "0.5m接驳台_1301030009",
  425 + "0.85m单轨伸缩过道_1301070001",
  426 + "0.85m单轨伸缩过道_1301070002",
  427 + "0.5m接驳台_1301030010",
  428 + "转角机_1301030002",
  429 + "0.5m接驳台_1301030011",
  430 + "0.5m移载机_130108003",
  431 + "0.5m双轨接驳台_1301030012",
  432 + "回流焊_1103050001",
  433 + "0.5m双轨接驳台_1301030013",
  434 + "0.5m移载机_1301080004",
  435 + "0.5m双轨接驳台_1301030014",
  436 + "双轨储板机_1301050001",
  437 + "0.5m双轨接驳台_1301030015",
  438 + "AOI_1201030001",
  439 + "0.5m双轨接驳台_1301030016",
  440 + "0.5m移载机_1301080005",
  441 + "0.5m接驳台_1301030017",
  442 + "0.8m单轨筛选接驳台_1301030018",
  443 + "0.5m接驳台_1301030019",
  444 + "转角机_1301030003",
  445 + "0.7m接驳台_1301030020",
  446 + "0.85m单轨伸缩过道_1301070003",
  447 + "翻板机_1301040001",
  448 + "0.7m接驳台_1301030021",
  449 + "转角机_1301030004",
  450 + "1m接驳台_1301030022",
  451 + "0.8米接驳台_1301030023",
  452 + "1.2米接驳台_1301030024",
  453 + "选择焊_1103050002",
  454 + "0.8m接驳台_1301030025",
  455 + "ICT测试_1202050001",
  456 + "0.8m接驳台_1301030026",
  457 + "双轨储板机_1301050002",
  458 + "0.8m接驳台_1301030027",
  459 + "分板机_1104060001",
  460 + "MPM印刷机_1102040003",
  461 + "德律SPI_1201010002",
  462 + "德律AOI_1201030002",
  463 + "多功能贴片机_1101010005",
  464 + "回流焊_1103050002",
  465 + "德律AOI_1201030003",
  466 + "离线分板机_1104060002",
  467 + "离线镭雕机_1101030002",
  468 + "离线ICT测试_1202050002",
  469 + "冲压机_1104060003",
  470 + "叠板上板机_1301010002",
  471 + "1米接驳台_1301030028",
  472 + "1米接驳台_1301030029",
  473 + "1米接驳台_1301030030",
  474 + "1米接驳台_1301030031",
  475 + "1米接驳台_1301030032",
  476 + "储板机(冷却)_1301050003",
  477 + "PCBA烧录屏蔽罩安装_1202080001",
  478 + "扬声器安装_1106100001",
  479 + "PCBA安装/FPC检测_1202060002",
  480 + "中控PCBA第三次烧录&后壳安装_1202060003",
  481 + "卡爪固定_1105070002",
  482 + "总成AOI EOL测试_1202060001",
  483 + "支架/散热硅胶安装_1105070001",
  484 + "后壳固定_1105090001",
  485 + "提升机_1301090001",
  486 + "Plasma清洁_1109140001",
  487 + "点胶_1111170001",
  488 + "TLCM与支架贴合_1110150003",
  489 + "后壳组装_1105090002",
  490 + "提升机_1301090002",
  491 + "UWB测试夹具_1101030002",
  492 + "UWB测试夹具_1101030003",
  493 + "UWB测试夹具_1101030004",
  494 + "UWB测试夹具_1101030005",
  495 + "UWB测试夹具_1101030006",
  496 + "HY11测试夹具_1111100001",
  497 + "HY11测试夹具_1111100002",
  498 + "离线ICT_1202050003",
  499 + "离线烧录_1111170001",
  500 + "离线3D X-Ray_1202090001",
  501 + "脱泡机_1107110003",
  502 + "半自动OCA贴合机_1110150003",
  503 + "半自动背光点胶组装机_1106100005",
  504 + "热拆解返修_1106100006",
  505 + "清胶返修_1106100007",
  506 + "切割返修_1106100008",
  507 + "展威切割机_1104060005",
  508 + "展威切割机_1104060006",
  509 + "喷码机_1111190004",
  510 + "钢网清洗机_1401010001",
  511 + "钢网检查机_1401010002",
  512 + "干燥箱_1401010003",
  513 + "干燥箱_1401030002",
  514 + "干燥箱_1401030003",
  515 + "干燥箱_1401030004",
  516 + "点料机_1401060001",
  517 + "点料机_1401060002",
  518 + "锡膏搅拌机_1401070001",
  519 + "抽真空机_1401110001",
  520 + "电烙铁_1401140001",
  521 + "炉温测试仪_1401150001",
  522 + "应力测试仪_1202060001",
  523 + "Tray清洗机_001",
  524 + "喷淋工位_002",
  525 + "抖动1工位_003",
  526 + "抖动2工位_004",
  527 + "抖动3工位_005",
  528 + "烘干1工位_006",
  529 + "烘干2工位_007",
  530 + "烘干3工位_008",
  531 + "烘干4工位_009",
  532 + "大尺寸Tary水洗机_010",
  533 + "喷淋1工位_011",
  534 + "喷淋2工位_012",
  535 + "喷淋3工位_013",
  536 + "烘干1工位_014",
  537 + "烘干2工位_015",
  538 + "烘干3工位_016",
  539 + "烘干4工位_017",
  540 + "烘干5工位_018",
  541 + "风刀背板清洗机_024",
  542 + "水洗背板清洗机_025",
  543 + "喷淋1工位_026",
  544 + "喷淋2工位_027",
  545 + "喷淋3工位_028",
  546 + "烘干1工位_029",
  547 + "烘干2工位_030",
  548 + "烘干3工位_031",
  549 + "烘干4工位_032",
  550 + "烘干5工位_033",
  551 + "烘干6工位_034",
  552 + "胶框清洗机_039",
  553 + "超声波工位_040",
  554 + "喷淋1工位_041",
  555 + "喷淋2工位_042",
  556 + "烘干1工位_043",
  557 + "烘干2工位_044",
  558 + "烘干3工位_045",
  559 + "烘干4工位_046",
  560 + "烘干5工位_047",
  561 + "三合一小尺寸膜片清洗机_051",
  562 + "三合一大尺寸膜片清洗机_052",
  563 + "膜片单清设备_053",
  564 + "单工位AOI_054",
  565 + "离线背板贴胶机_055",
  566 + "离线LGP组装设备_056",
  567 + "胶条1工位_057",
  568 + "胶条2工位_058",
  569 + "滚压1工位_059",
  570 + "胶条3工位_060",
  571 + "滚压2工位_061",
  572 + "反射片组装工位_062",
  573 + "覆膜工位_063",
  574 + "离线胶框贴胶机_064",
  575 + "离线背板侧壁贴胶机_065",
  576 + "背板侧壁胶工位_066",
  577 + "LB导热胶工位_067",
  578 + "反射片固定胶工位_068",
  579 + "覆膜机_069",
  580 + "泡棉贴胶机_070",
  581 + "胶条1工位_071",
  582 + "胶条2工位_072",
  583 + "胶条3工位_073",
  584 + "胶条4工位_074",
  585 + "划压工位_075",
  586 + "撕膜1工位_076",
  587 + "撕膜2工位_077",
  588 + "称重工位_078",
  589 + "背板贴胶机_079",
  590 + "膜片组装机_080",
  591 + "扩散工位_081",
  592 + "增光工位_082",
  593 + "DBEF工位_083",
  594 + "防窥膜工位_084",
  595 + "覆膜机_085",
  596 + "背板贴胶机_086",
  597 + "膜片组装机_087",
  598 + "扩散工位_088",
  599 + "增光工位_089",
  600 + "DBEF工位_090",
  601 + "防窥膜工位_091",
  602 + "膜移检测工位_092",
  603 + "扣框工位_093",
  604 + "胶框保压工位_094",
  605 + "前加工设备_095",
  606 + "PCB工位_096",
  607 + "标签+小黑胶工位_097",
  608 + "翻转工位_098",
  609 + "堵孔1工位_099",
  610 + "堵孔2工位_100",
  611 + "灯条侧边胶工位_101",
  612 + "导热胶工位_102",
  613 + "反射片固定胶工位_103",
  614 + "泡棉贴胶机_104",
  615 + "胶条1工位_105",
  616 + "胶条2工位_106",
  617 + "胶条3工位_107",
  618 + "胶条4工位_108",
  619 + "划压工位_109",
  620 + "半成品组装_110",
  621 + "LB保压工位_111",
  622 + "胶条1工位_112",
  623 + "滚压1工位_113",
  624 + "胶条2工位_114",
  625 + "滚压2工位_115",
  626 + "胶条3工位_116",
  627 + "滚压3工位_117",
  628 + "胶条4工位_118",
  629 + "撕膜工位_119",
  630 + "反射片贴合工位_120",
  631 + "导光板组装工位_121",
  632 + "CCD检查+搬运工位_122",
  633 + "膜间胶1工位_123",
  634 + "扩散工位_124",
  635 + "膜间胶2工位_125",
  636 + "增光工位_126",
  637 + "膜间胶3工位_127",
  638 + "DBEF工位_128",
  639 + "膜间胶4工位_129",
  640 + "防窥膜工位_130",
  641 + "膜移检测工位_131",
  642 + "扣框工位_132",
  643 + "包边机_133",
  644 + "胶条1工位_134",
  645 + "胶条2工位_135",
  646 + "胶条3工位_136",
  647 + "胶条4工位_137",
  648 + "撕膜1工位_138",
  649 + "撕膜2工位_139",
  650 + "PET工位_140",
  651 + "覆膜机_141",
  652 + "自动AOI_142",
  653 + "AVI_143",
  654 + "半自动CCD检查设备_144",
  655 + "大尺寸CCD检查设备_145",
  656 + "喷码机_146",
  657 + "螺纹柱检查设备_147"
  658 + );
  659 + }
  660 +
  661 + // 保留原方法以保持兼容性
  662 + public void pullDeviceAndPushToIot() {
  663 + pullDeviceAndPushToIot(true);
  664 + }
  665 +
  666 + public void pullDeviceAndPushToIot2() {
  667 + pullDeviceAndPushToIot(false);
  668 + }
  669 +
218 public String getDeviceInfoDetail(String dtuSn) { 670 public String getDeviceInfoDetail(String dtuSn) {
219 String accessToken = getAccessToken(); 671 String accessToken = getAccessToken();
220 Map<String, String> dtuSnOb = new HashMap<>(1); 672 Map<String, String> dtuSnOb = new HashMap<>(1);
@@ -25,7 +25,18 @@ public class BjkjZoneScheduler extends AbstractZoneScheduler { @@ -25,7 +25,18 @@ public class BjkjZoneScheduler extends AbstractZoneScheduler {
25 logStart(taskName); 25 logStart(taskName);
26 try { 26 try {
27 log.info("[{}] Simulating pulling devices...", getZoneName()); 27 log.info("[{}] Simulating pulling devices...", getZoneName());
28 - bjkjDevicePullService.pullDeviceAndPushToIot(); 28 +
  29 + // 使用原子变量或计数器来判断是真实数据还是假数据
  30 + boolean useRealData = shouldUseRealData();
  31 +
  32 + if (useRealData) {
  33 + log.info("本次执行:同步真实设备数据");
  34 + bjkjDevicePullService.pullDeviceAndPushToIot(true); // 从远程接口获取真实数据
  35 + } else {
  36 + log.info("本次执行:同步模拟设备数据(本地设备列表)");
  37 + bjkjDevicePullService.pullDeviceAndPushToIot(false); // 使用本地设备列表生成模拟数据
  38 + }
  39 +
29 Thread.sleep(1000); 40 Thread.sleep(1000);
30 } catch (Exception e) { 41 } catch (Exception e) {
31 logError(taskName, e); 42 logError(taskName, e);
@@ -33,4 +44,14 @@ public class BjkjZoneScheduler extends AbstractZoneScheduler { @@ -33,4 +44,14 @@ public class BjkjZoneScheduler extends AbstractZoneScheduler {
33 logEnd(taskName); 44 logEnd(taskName);
34 } 45 }
35 } 46 }
  47 +
  48 + // 方案一:使用原子整数计数器
  49 + private final java.util.concurrent.atomic.AtomicInteger executeCount = new java.util.concurrent.atomic.AtomicInteger(0);
  50 +
  51 + private boolean shouldUseRealData() {
  52 + int count = executeCount.incrementAndGet();
  53 + // 奇数执行真实数据,偶数执行假数据
  54 + return count % 2 == 1;
  55 + }
  56 +
36 } 57 }