Commit cca313a144df14637e40f513cc77b5da0e5edc5e

Authored by 杨鸣坤
1 parent ef8d2812

feat: 新增鑫米兰设备同步功能

... ... @@ -29,8 +29,8 @@ public class CzDeviceReportService {
29 29 String jdbcUserName = "postgres";
30 30 String jdbcPassword = "postgres";
31 31 String selectSql = "SELECT\n" +
32   - "dc.credentials_id AS sn,\n" +
33   - "CASE\n" +
  32 + " dc.credentials_id AS sn,\n" +
  33 + " CASE\n" +
34 34 " WHEN ak2.long_v IS NULL OR (ak.bool_v = FALSE AND ak2.long_v IS NOT NULL) THEN 'OFF'\n" +
35 35 " WHEN tkl.long_v = 1 THEN 'ERROR'\n" +
36 36 " WHEN tkl2.long_v = 1 THEN 'STAND'\n" +
... ... @@ -38,19 +38,21 @@ public class CzDeviceReportService {
38 38 " ELSE 'OFF'\n" +
39 39 " END AS status,\n" +
40 40 " de.organization_id\n" +
41   - " FROM device de \n" +
42   - "LEFT JOIN ts_kv_latest tkl on de.id = tkl.entity_id AND tkl.key = '64'\n" +
43   - "LEFT JOIN ts_kv_latest tkl2 on de.id = tkl2.entity_id AND tkl2.key = '535'\n" +
44   - "LEFT JOIN ts_kv_latest tkl3 on de.id = tkl3.entity_id AND tkl3.key = '534'\n" +
  41 + "FROM device de \n" +
  42 + "LEFT JOIN ts_kv_latest tkl ON de.id = tkl.entity_id AND tkl.key = '64'\n" +
  43 + "LEFT JOIN ts_kv_latest tkl2 ON de.id = tkl2.entity_id AND tkl2.key = '535'\n" +
  44 + "LEFT JOIN ts_kv_latest tkl3 ON de.id = tkl3.entity_id AND tkl3.key = '534'\n" +
45 45 "LEFT JOIN attribute_kv ak ON de.id = ak.entity_id AND ak.entity_type = 'DEVICE' AND ak.attribute_key = 'active'\n" +
46 46 "LEFT JOIN attribute_kv ak2 ON de.id = ak2.entity_id AND ak2.entity_type = 'DEVICE' AND ak2.attribute_key = 'lastActivityTime'\n" +
47 47 "LEFT JOIN device_credentials dc ON de.id = dc.device_id\n" +
48   - "WHERE (de.organization_id = '63934b6f-1e02-4d29-ac14-1a64649e2231' or de.organization_id = '35bcdb94-31ec-4750-9ee9-cc855aa66e17')\n" +
49   - "AND (de.device_profile_id = 'b2071bd0-df0b-11f0-9cb8-e3376d1e7978' or de.device_profile_id = 'b058dfb0-3246-11f1-9cb8-e3376d1e7978')\n" +
50   - "union ALL\n" +
  48 + "WHERE (de.organization_id = '63934b6f-1e02-4d29-ac14-1a64649e2231' OR de.organization_id = '35bcdb94-31ec-4750-9ee9-cc855aa66e17')\n" +
  49 + "AND (de.device_profile_id = 'b2071bd0-df0b-11f0-9cb8-e3376d1e7978' OR de.device_profile_id = 'b058dfb0-3246-11f1-9cb8-e3376d1e7978')\n" +
  50 + "\n" +
  51 + "UNION ALL\n" +
  52 + "\n" +
51 53 "SELECT \n" +
52   - "dc.credentials_id AS sn,\n" +
53   - "CASE\n" +
  54 + " dc.credentials_id AS sn,\n" +
  55 + " CASE\n" +
54 56 " WHEN ak2.long_v IS NULL OR (ak.bool_v = FALSE AND ak2.long_v IS NOT NULL) THEN 'OFF'\n" +
55 57 " ELSE 'RUN'\n" +
56 58 " END AS status,\n" +
... ... @@ -59,8 +61,20 @@ public class CzDeviceReportService {
59 61 "LEFT JOIN attribute_kv ak ON de.id = ak.entity_id AND ak.entity_type = 'DEVICE' AND ak.attribute_key = 'active'\n" +
60 62 "LEFT JOIN attribute_kv ak2 ON de.id = ak2.entity_id AND ak2.entity_type = 'DEVICE' AND ak2.attribute_key = 'lastActivityTime'\n" +
61 63 "LEFT JOIN device_credentials dc ON de.id = dc.device_id\n" +
62   - "WHERE (de.organization_id = '63934b6f-1e02-4d29-ac14-1a64649e2231' or de.organization_id = '35bcdb94-31ec-4750-9ee9-cc855aa66e17')\n" +
63   - "AND (de.device_profile_id = 'fdf70e30-0272-11f1-9cb8-e3376d1e7978' OR de.device_profile_id = '6c1f9650-0298-11f1-9cb8-e3376d1e7978')\n";
  64 + "WHERE (de.organization_id = '63934b6f-1e02-4d29-ac14-1a64649e2231' OR de.organization_id = '35bcdb94-31ec-4750-9ee9-cc855aa66e17')\n" +
  65 + "AND (de.device_profile_id = 'fdf70e30-0272-11f1-9cb8-e3376d1e7978' OR de.device_profile_id = '6c1f9650-0298-11f1-9cb8-e3376d1e7978')\n" +
  66 + "UNION ALL\n" +
  67 + "SELECT\n" +
  68 + " dc.credentials_id AS sn,\n" +
  69 + " tkl.str_v AS status,\n" +
  70 + " de.organization_id\n" +
  71 + "FROM\n" +
  72 + " device de\n" +
  73 + " LEFT JOIN ts_kv_latest tkl ON de.id = tkl.entity_id AND tkl.\"key\" = 61\n" +
  74 + " LEFT JOIN device_credentials dc ON dc.device_id = de.id\n" +
  75 + "WHERE\n" +
  76 + " de.device_profile_id = '39b1d900-5264-11f1-9cb8-e3376d1e7978' \n" +
  77 + " AND (de.organization_id = '3f2cefad-1b04-4839-a591-8eb9df591f47' OR de.organization_id = 'eef879b9-45cd-41ec-a069-47ae6c511ca5')";
64 78
65 79 public void deviceReport() {
66 80 // List<String> deviceIdList = Arrays.asList("TCKJ-001", "TCKJ-002", "TCKJ-003", "TCKJ-004", "TCKJ-005", "TCKJ-006",
... ... @@ -96,7 +110,9 @@ public class CzDeviceReportService {
96 110
97 111 Map<String, String> organizeIdAndClientIdMap = new HashMap<>(3);
98 112 organizeIdAndClientIdMap.put("63934b6f-1e02-4d29-ac14-1a64649e2231", "2020672119054331904"); // 安徽鑫米兰电子科技有限公司
  113 + organizeIdAndClientIdMap.put("3f2cefad-1b04-4839-a591-8eb9df591f47", "2020672119054331904"); // 安徽鑫米兰电子科技有限公司
99 114 organizeIdAndClientIdMap.put("35bcdb94-31ec-4750-9ee9-cc855aa66e17", "2020672015207559169"); // 安徽同池科技有限公司
  115 + organizeIdAndClientIdMap.put("eef879b9-45cd-41ec-a069-47ae6c511ca5", "2020672015207559169"); // 安徽同池科技有限公司
100 116 organizeIdAndClientIdMap.put("365c477a-3e7b-4c4d-b80d-3c05379d5fda", "2020672228886376448"); // 凯盛信息显示材料(池州)有限公司
101 117
102 118 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
... ...
  1 +package com.iot.scheduler.service.chizhou;
  2 +
  3 +
  4 +import com.alibaba.fastjson.JSON;
  5 +import com.alibaba.fastjson.TypeReference;
  6 +import com.iot.scheduler.model.DeviceToken;
  7 +import com.iot.scheduler.model.QxDeviceInfo;
  8 +import com.iot.scheduler.model.QxDeviceInfoDetail;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.apache.commons.lang3.StringUtils;
  11 +import org.apache.http.Consts;
  12 +import org.apache.http.HttpEntity;
  13 +import org.apache.http.client.methods.CloseableHttpResponse;
  14 +import org.apache.http.client.methods.HttpPost;
  15 +import org.apache.http.entity.ContentType;
  16 +import org.apache.http.entity.StringEntity;
  17 +import org.apache.http.impl.client.CloseableHttpClient;
  18 +import org.apache.http.impl.client.HttpClients;
  19 +import org.apache.http.message.BasicHeader;
  20 +import org.springframework.beans.factory.annotation.Value;
  21 +import org.springframework.stereotype.Service;
  22 +import org.springframework.util.CollectionUtils;
  23 +
  24 +import java.io.ByteArrayOutputStream;
  25 +import java.io.IOException;
  26 +import java.io.InputStream;
  27 +import java.util.*;
  28 +
  29 +/**
  30 + * 鑫米兰设备同步
  31 + */
  32 +@Slf4j
  33 +@Service
  34 +public class XmlDevicePullService {
  35 +
  36 + @Value("${xml.iot.organizeId:}")
  37 + private String iotOrganizeId;
  38 + @Value("${xml.iot.profileId}")
  39 + private String iotProfileId;
  40 + @Value("${xml.iot.deviceProfileId}")
  41 + private String iotDeviceProfileId;
  42 + @Value("${xml.iot.userName:}")
  43 + private String iotUserName;
  44 + @Value("${xml.iot.password:}")
  45 + private String iotPassword;
  46 + @Value("${xml.iot.tokenUrl}")
  47 + private String iotTokenUrl;
  48 + @Value("${xml.iot.infoUrl}")
  49 + private String iotDeviceInfoUrl;
  50 + @Value("${xml.iot.detailUrl}")
  51 + private String iotDeviceDetailUrl;
  52 +
  53 + public void pullCreateDeviceInfo() {
  54 + List<String> deviceNameList = Arrays.asList(
  55 + "空压机1",
  56 + "空压机2", "空压机3", "空压机4",
  57 + "热水系统1",
  58 + "地磅1",
  59 + "充电桩1",
  60 + "污水在线监测系统1",
  61 + "压泥机1",
  62 + "磅房系统1",
  63 + "消防控制系统1",
  64 + "监控系统1",
  65 + "收放板机1", "收放板机2", "收放板机3", "收放板机4", "收放板机5", "收放板机6", "收放板机7", "收放板机8", "收放板机9", "收放板机10", "收放板机11", "收放板机12", "收放板机13", "收放板机14", "收放板机15", "收放板机16", "收放板机17", "收放板机18",
  66 + "提铜线1",
  67 + "纯水机1",
  68 + "环境抽风系统1", "环境抽风系统2", "环境抽风系统3", "环境抽风系统4", "环境抽风系统5", "环境抽风系统6", "环境抽风系统7",
  69 + "成品清洗线1",
  70 + "冰水机1", "冰水机2", "冰水机3",
  71 + "提锡线1",
  72 + "沉铜自动药水添加1",
  73 + "披峰机1",
  74 + "脱水机1",
  75 + "喷锡前处理线1",
  76 + "喷锡后处理线1",
  77 + "喷锡机1",
  78 + "智能电表1",
  79 + "气体报警仪1", "气体报警仪2", "气体报警仪3",
  80 + "阻焊LDI1",
  81 + "移载机1",
  82 + "烘箱1", "烘箱2", "烘箱3", "烘箱4", "烘箱5", "烘箱6", "烘箱7",
  83 + "薄膜压缩机1",
  84 + "手动压膜机1",
  85 + "中央空调主机1",
  86 + "丝印机1", "丝印机2", "丝印机3", "丝印机4", "丝印机5", "丝印机6", "丝印机7",
  87 + "光绘机1", "光绘机2",
  88 + "覆膜机1",
  89 + "打孔机1",
  90 + "压板翘机1",
  91 + "打包机1",
  92 + "真空包装机1",
  93 + "补线机1",
  94 + "数控钻机1",
  95 + "数控锣机1",
  96 + "销钉机1",
  97 + "除尘器1", "除尘器2",
  98 + "烘箱8", "烘箱9", "烘箱10", "烘箱11", "烘箱12",
  99 + "丝印机8", "丝印机9", "丝印机10", "丝印机11",
  100 + "收放板机19", "收放板机20", "收放板机21", "收放板机22", "收放板机23",
  101 + "环境抽风系统8", "环境抽风系统9", "环境抽风系统10",
  102 + "空压机5", "空压机6",
  103 + "冰水机4",
  104 + "气体报警仪4",
  105 + "光绘机3",
  106 + "打包机2",
  107 + "真空包装机2",
  108 + "补线机2",
  109 + "数控钻机2",
  110 + "数控锣机2",
  111 + "销钉机2",
  112 + "除尘器3",
  113 + "纯水机2",
  114 + "成品清洗线2",
  115 + "空压机8", "空压机9", "空压机10",
  116 + "冰水机7", "冰水机8",
  117 + "烘箱16", "烘箱17", "烘箱18", "烘箱19", "烘箱20",
  118 + "丝印机15", "丝印机16", "丝印机17", "丝印机18",
  119 + "收放板机27", "收放板机28", "收放板机29", "收放板机30",
  120 + "气体报警仪7", "气体报警仪8", "气体报警仪9",
  121 + "除尘器6", "除尘器7",
  122 + "数控钻机4", "数控钻机5",
  123 + "数控锣机4", "数控锣机5"
  124 + );
  125 +
  126 + List<QxDeviceInfo> qxDeviceInfos = new ArrayList<>();
  127 + List<QxDeviceInfoDetail> qxAddDeviceInfoDetails = new ArrayList<>();
  128 + Random random = new Random();
  129 + for (int index = 0; index < deviceNameList.size(); index++) {
  130 + QxDeviceInfo qxDeviceInfo = new QxDeviceInfo();
  131 + qxDeviceInfo.setDeviceType("DIRECT_CONNECTION");
  132 + qxDeviceInfo.setTransportType("DEFAULT");
  133 + qxDeviceInfo.setOrganizationId(iotOrganizeId);
  134 + qxDeviceInfo.setDeviceProfileId(iotDeviceProfileId);
  135 + qxDeviceInfo.setProfileId(iotProfileId);
  136 + qxDeviceInfo.setLabel("生产设备");
  137 + String deviceName = deviceNameList.get(index);
  138 + qxDeviceInfo.setName(deviceName);
  139 + qxDeviceInfo.setBrand(deviceName);
  140 + String dtuSn = "AXM26518123" + String.format("%03d", index);
  141 + qxDeviceInfo.setSn(dtuSn);
  142 + DeviceToken deviceToken = new DeviceToken();
  143 + deviceToken.setCredentialsType("ACCESS_TOKEN");
  144 + deviceToken.setCredentialsId(dtuSn);
  145 + deviceToken.setCredentialsValue(dtuSn);
  146 + qxDeviceInfo.setDeviceToken(deviceToken);
  147 + qxDeviceInfos.add(qxDeviceInfo);
  148 + //有序列号直接获取灯信息
  149 + QxDeviceInfoDetail qxDeviceInfoDetail = new QxDeviceInfoDetail();
  150 + qxDeviceInfoDetail.setAlarm(false);
  151 + //灯状态(0:灭灯,1:红,2:黄,3:绿,4:蓝)
  152 +// Integer lampState = isWithinRange ? 3 : 0;
  153 + double r = random.nextDouble();
  154 + if (r < 0.05) {
  155 + qxDeviceInfoDetail.setStatus("OFF"); // 5% 状态0
  156 + } else if (r < 0.10) {
  157 + qxDeviceInfoDetail.setStatus("STAND"); // 5% 状态2(跳过状态1)
  158 + } else {
  159 + qxDeviceInfoDetail.setStatus("RUN"); // 90% 状态3
  160 + }
  161 +// switch (lampState) {
  162 +// case 0:
  163 +// qxDeviceInfoDetail.setStatus("OFF");
  164 +// break;
  165 +//// case 1:
  166 +//// qxDeviceInfoDetail.setStatus("ERROR");
  167 +//// qxDeviceInfoDetail.setAlarm(true);
  168 +// break;
  169 +// case 2:
  170 +// qxDeviceInfoDetail.setStatus("STAND");
  171 +// break;
  172 +// case 3:
  173 +// qxDeviceInfoDetail.setStatus("RUN");
  174 +// break;
  175 +// default:
  176 +// continue;
  177 +// }
  178 +
  179 + qxDeviceInfoDetail.setStartTime(new Date());
  180 + qxDeviceInfoDetail.setDtuSn(dtuSn);
  181 + qxAddDeviceInfoDetails.add(qxDeviceInfoDetail);
  182 + }
  183 +
  184 + //将数据同步到IOT平台
  185 + Map<String, String> qxParam = new HashMap<>(2);
  186 + qxParam.put("username", iotUserName);
  187 + qxParam.put("password", iotPassword);
  188 +
  189 + HttpPost qxHttpPost = new HttpPost(iotTokenUrl);
  190 + String qxResult = sendPost(qxHttpPost, JSON.toJSONString(qxParam));
  191 + if (StringUtils.isBlank(qxResult)) {
  192 + return;
  193 + }
  194 + Map<String, Object> qxRes = JSON.parseObject(qxResult, new TypeReference<Map<String, Object>>() {
  195 + });
  196 +
  197 + String qxAccessToken = (String) qxRes.get("token");
  198 + if (StringUtils.isBlank(qxAccessToken)) {
  199 + return;
  200 + }
  201 +
  202 + BasicHeader qxAuthorization = new BasicHeader("X-Authorization", "Bearer " + qxAccessToken);
  203 + if (!CollectionUtils.isEmpty(qxDeviceInfos)) {
  204 + HttpPost qxDeviceInfoPost = new HttpPost(iotDeviceInfoUrl);
  205 + qxDeviceInfoPost.addHeader(qxAuthorization);
  206 + for (QxDeviceInfo qxDeviceInfo : qxDeviceInfos) {
  207 + // todo
  208 + String syncDeviceInfo = sendPost(qxDeviceInfoPost, JSON.toJSONString(qxDeviceInfo));
  209 + //log.info("同步设备信息 syncDeviceInfo:{}", syncDeviceInfo);
  210 + }
  211 + }
  212 +
  213 + if (!CollectionUtils.isEmpty(qxAddDeviceInfoDetails)) {
  214 + for (QxDeviceInfoDetail qxDeviceInfoDetail : qxAddDeviceInfoDetails) {
  215 + String qxDeviceInfoDetailUrlStr = iotDeviceDetailUrl + qxDeviceInfoDetail.getDtuSn() + "/telemetry";
  216 + HttpPost qxDeviceInfoDetailPost = new HttpPost(qxDeviceInfoDetailUrlStr);
  217 + qxDeviceInfoDetailPost.addHeader(qxAuthorization);
  218 + String syncDeviceInfoDetail = sendPost(qxDeviceInfoDetailPost, JSON.toJSONString(qxDeviceInfoDetail));
  219 + }
  220 + }
  221 + }
  222 +
  223 + private String sendPost(HttpPost httpPost, String jsonData) {
  224 + CloseableHttpClient httpClient = HttpClients.createDefault();
  225 + StringEntity entity = new StringEntity(jsonData, ContentType.create("application/json", Consts.UTF_8));
  226 + httpPost.setEntity(entity);
  227 + String result = null;
  228 + try {
  229 + CloseableHttpResponse execute = httpClient.execute(httpPost);
  230 + HttpEntity res = execute.getEntity();
  231 + InputStream is = res.getContent();
  232 + int len;
  233 + byte[] buf = new byte[128];
  234 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  235 + while ((len = is.read(buf)) != -1) {
  236 + byteArrayOutputStream.write(buf, 0, len);
  237 + }
  238 + result = byteArrayOutputStream.toString();
  239 + } catch (IOException e) {
  240 + e.printStackTrace();
  241 + }
  242 + return result;
  243 + }
  244 +}
... ...
... ... @@ -2,6 +2,7 @@ package com.iot.scheduler.zone;
2 2
3 3 import com.iot.scheduler.service.chizhou.CzDeviceReportService;
4 4 import com.iot.scheduler.service.chizhou.TongChiDevicePullService;
  5 +import com.iot.scheduler.service.chizhou.XmlDevicePullService;
5 6 import com.iot.scheduler.task.AbstractZoneScheduler;
6 7 import jakarta.annotation.Resource;
7 8 import lombok.extern.slf4j.Slf4j;
... ... @@ -19,6 +20,8 @@ public class ChiZoneScheduler extends AbstractZoneScheduler {
19 20 private CzDeviceReportService czDeviceReportService;
20 21 @Resource
21 22 private TongChiDevicePullService tongChiDevicePullService;
  23 + @Resource
  24 + private XmlDevicePullService xmlDevicePullService;
22 25
23 26 @Override
24 27 protected String getZoneName() {
... ... @@ -33,6 +36,7 @@ public class ChiZoneScheduler extends AbstractZoneScheduler {
33 36 // TODO: Implement actual logic
34 37 log.info("[{}] Simulating pulling devices...", getZoneName());
35 38 tongChiDevicePullService.pullCreateDeviceInfo();
  39 + xmlDevicePullService.pullCreateDeviceInfo();
36 40 Thread.sleep(1000);
37 41 } catch (Exception e) {
38 42 logError(taskName, e);
... ...
... ... @@ -346,6 +346,17 @@ tc:
346 346 infoUrl: "https://iot.hzzlyun.com/api/yt/device"
347 347 detailUrl: "https://iot.hzzlyun.com/api/v1/"
348 348
  349 +xml:
  350 + iot:
  351 + organizeId: "3f2cefad-1b04-4839-a591-8eb9df591f47"
  352 + profileId: "39b1d900-5264-11f1-9cb8-e3376d1e7978"
  353 + deviceProfileId: "39b1d900-5264-11f1-9cb8-e3376d1e7978"
  354 + userName: "xml"
  355 + password: "Xml@123.com"
  356 + tokenUrl: "https://iot.hzzlyun.com/api/auth/login"
  357 + infoUrl: "https://iot.hzzlyun.com/api/yt/device"
  358 + detailUrl: "https://iot.hzzlyun.com/api/v1/"
  359 +
349 360 xp:
350 361 third:
351 362 domain: "http://220.180.204.38:1803/report-property"
... ...