diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/casic/util/HttpClientUtil.java b/src/main/java/com/casic/util/HttpClientUtil.java new file mode 100644 index 0000000..ca92b11 --- /dev/null +++ b/src/main/java/com/casic/util/HttpClientUtil.java @@ -0,0 +1,141 @@ +package com.casic.util; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class HttpClientUtil { + + public static String doGet(String url, Map param) { + + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return resultString; + } + + public static String doPost(String url) { + return doPost(url, null); + } + + public static String doPostJson(String json, String url) throws Exception { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setSocketTimeout(3000) + .setConnectTimeout(3000) + .build(); + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception ex) { + throw ex; + } finally { + if (null != response) { + response.close(); + } + if (null != httpClient) { + httpClient.close(); + } + } + + return resultString; + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/casic/util/HttpClientUtil.java b/src/main/java/com/casic/util/HttpClientUtil.java new file mode 100644 index 0000000..ca92b11 --- /dev/null +++ b/src/main/java/com/casic/util/HttpClientUtil.java @@ -0,0 +1,141 @@ +package com.casic.util; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class HttpClientUtil { + + public static String doGet(String url, Map param) { + + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return resultString; + } + + public static String doPost(String url) { + return doPost(url, null); + } + + public static String doPostJson(String json, String url) throws Exception { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setSocketTimeout(3000) + .setConnectTimeout(3000) + .build(); + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception ex) { + throw ex; + } finally { + if (null != response) { + response.close(); + } + if (null != httpClient) { + httpClient.close(); + } + } + + return resultString; + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/Server.java b/src/main/java/com/casic/util/Server.java new file mode 100644 index 0000000..327da37 --- /dev/null +++ b/src/main/java/com/casic/util/Server.java @@ -0,0 +1,38 @@ +package com.casic.util; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 服务器socket + */ +public class Server { + public static void main(String[] args) { + try { + ServerSocket serverSocket = new ServerSocket(11321); + System.out.println("----------------服务端执行,開始监听请求----------------"); + + Socket socket = serverSocket.accept();//開始监听 + InputStream inputStream = socket.getInputStream(); + //获取请求内容 + String info; + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((info = bufferedReader.readLine()) != null) { + System.out.println("我是服务端,客户端请求为:" + info); + } + //关闭资源 + socket.shutdownInput(); + bufferedReader.close(); + inputStream.close(); + socket.close(); + serverSocket.close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/casic/util/HttpClientUtil.java b/src/main/java/com/casic/util/HttpClientUtil.java new file mode 100644 index 0000000..ca92b11 --- /dev/null +++ b/src/main/java/com/casic/util/HttpClientUtil.java @@ -0,0 +1,141 @@ +package com.casic.util; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class HttpClientUtil { + + public static String doGet(String url, Map param) { + + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return resultString; + } + + public static String doPost(String url) { + return doPost(url, null); + } + + public static String doPostJson(String json, String url) throws Exception { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setSocketTimeout(3000) + .setConnectTimeout(3000) + .build(); + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception ex) { + throw ex; + } finally { + if (null != response) { + response.close(); + } + if (null != httpClient) { + httpClient.close(); + } + } + + return resultString; + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/Server.java b/src/main/java/com/casic/util/Server.java new file mode 100644 index 0000000..327da37 --- /dev/null +++ b/src/main/java/com/casic/util/Server.java @@ -0,0 +1,38 @@ +package com.casic.util; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 服务器socket + */ +public class Server { + public static void main(String[] args) { + try { + ServerSocket serverSocket = new ServerSocket(11321); + System.out.println("----------------服务端执行,開始监听请求----------------"); + + Socket socket = serverSocket.accept();//開始监听 + InputStream inputStream = socket.getInputStream(); + //获取请求内容 + String info; + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((info = bufferedReader.readLine()) != null) { + System.out.println("我是服务端,客户端请求为:" + info); + } + //关闭资源 + socket.shutdownInput(); + bufferedReader.close(); + inputStream.close(); + socket.close(); + serverSocket.close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/ServerSocketUtil.java b/src/main/java/com/casic/util/ServerSocketUtil.java new file mode 100644 index 0000000..830aca0 --- /dev/null +++ b/src/main/java/com/casic/util/ServerSocketUtil.java @@ -0,0 +1,41 @@ +package com.casic.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.net.Socket; +import java.net.UnknownHostException; + +@Component +public class ServerSocketUtil { + + @Value("${casic.host}") + private String host; + @Value("${casic.port}") + private Integer port; + + public String sendMsg(String Json) throws UnknownHostException, IOException { + + // 向服务器端发送请求,服务器IP地址和服务器监听的端口号 + Socket server = new Socket(host, port); + if(!server.isConnected()){ + return "11"; + } + + OutputStream os = server.getOutputStream(); + //把输出流封装在DataOutputStream中 + DataOutputStream dos = new DataOutputStream(os); + //使用writeUTF发送字符串 + dos.writeUTF("Legendary!"); + dos.flush(); + dos.close(); + server.close(); +// System.out.println("连接已建立..."); +// // 发送消息 +// printWriter.println(Json); +// printWriter.flush(); + return "200"; + } + +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/casic/util/HttpClientUtil.java b/src/main/java/com/casic/util/HttpClientUtil.java new file mode 100644 index 0000000..ca92b11 --- /dev/null +++ b/src/main/java/com/casic/util/HttpClientUtil.java @@ -0,0 +1,141 @@ +package com.casic.util; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class HttpClientUtil { + + public static String doGet(String url, Map param) { + + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return resultString; + } + + public static String doPost(String url) { + return doPost(url, null); + } + + public static String doPostJson(String json, String url) throws Exception { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setSocketTimeout(3000) + .setConnectTimeout(3000) + .build(); + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception ex) { + throw ex; + } finally { + if (null != response) { + response.close(); + } + if (null != httpClient) { + httpClient.close(); + } + } + + return resultString; + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/Server.java b/src/main/java/com/casic/util/Server.java new file mode 100644 index 0000000..327da37 --- /dev/null +++ b/src/main/java/com/casic/util/Server.java @@ -0,0 +1,38 @@ +package com.casic.util; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 服务器socket + */ +public class Server { + public static void main(String[] args) { + try { + ServerSocket serverSocket = new ServerSocket(11321); + System.out.println("----------------服务端执行,開始监听请求----------------"); + + Socket socket = serverSocket.accept();//開始监听 + InputStream inputStream = socket.getInputStream(); + //获取请求内容 + String info; + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((info = bufferedReader.readLine()) != null) { + System.out.println("我是服务端,客户端请求为:" + info); + } + //关闭资源 + socket.shutdownInput(); + bufferedReader.close(); + inputStream.close(); + socket.close(); + serverSocket.close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/ServerSocketUtil.java b/src/main/java/com/casic/util/ServerSocketUtil.java new file mode 100644 index 0000000..830aca0 --- /dev/null +++ b/src/main/java/com/casic/util/ServerSocketUtil.java @@ -0,0 +1,41 @@ +package com.casic.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.net.Socket; +import java.net.UnknownHostException; + +@Component +public class ServerSocketUtil { + + @Value("${casic.host}") + private String host; + @Value("${casic.port}") + private Integer port; + + public String sendMsg(String Json) throws UnknownHostException, IOException { + + // 向服务器端发送请求,服务器IP地址和服务器监听的端口号 + Socket server = new Socket(host, port); + if(!server.isConnected()){ + return "11"; + } + + OutputStream os = server.getOutputStream(); + //把输出流封装在DataOutputStream中 + DataOutputStream dos = new DataOutputStream(os); + //使用writeUTF发送字符串 + dos.writeUTF("Legendary!"); + dos.flush(); + dos.close(); + server.close(); +// System.out.println("连接已建立..."); +// // 发送消息 +// printWriter.println(Json); +// printWriter.flush(); + return "200"; + } + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..9d9f8a7 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,20 @@ +server: + port: 11642 +################### spring配置 ################### +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://111.198.10.15:11102/smartwell_br_test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8&&allowMultiQueries=true + username: root + password: Casic203! + session: + store-type: redis + jms: + pub-sub-domain: true + +logging: + level.root: info + level.com.casic: info + file: + path: logs/ + name: missiles.log \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/casic/util/HttpClientUtil.java b/src/main/java/com/casic/util/HttpClientUtil.java new file mode 100644 index 0000000..ca92b11 --- /dev/null +++ b/src/main/java/com/casic/util/HttpClientUtil.java @@ -0,0 +1,141 @@ +package com.casic.util; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class HttpClientUtil { + + public static String doGet(String url, Map param) { + + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return resultString; + } + + public static String doPost(String url) { + return doPost(url, null); + } + + public static String doPostJson(String json, String url) throws Exception { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setSocketTimeout(3000) + .setConnectTimeout(3000) + .build(); + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception ex) { + throw ex; + } finally { + if (null != response) { + response.close(); + } + if (null != httpClient) { + httpClient.close(); + } + } + + return resultString; + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/Server.java b/src/main/java/com/casic/util/Server.java new file mode 100644 index 0000000..327da37 --- /dev/null +++ b/src/main/java/com/casic/util/Server.java @@ -0,0 +1,38 @@ +package com.casic.util; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 服务器socket + */ +public class Server { + public static void main(String[] args) { + try { + ServerSocket serverSocket = new ServerSocket(11321); + System.out.println("----------------服务端执行,開始监听请求----------------"); + + Socket socket = serverSocket.accept();//開始监听 + InputStream inputStream = socket.getInputStream(); + //获取请求内容 + String info; + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((info = bufferedReader.readLine()) != null) { + System.out.println("我是服务端,客户端请求为:" + info); + } + //关闭资源 + socket.shutdownInput(); + bufferedReader.close(); + inputStream.close(); + socket.close(); + serverSocket.close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/ServerSocketUtil.java b/src/main/java/com/casic/util/ServerSocketUtil.java new file mode 100644 index 0000000..830aca0 --- /dev/null +++ b/src/main/java/com/casic/util/ServerSocketUtil.java @@ -0,0 +1,41 @@ +package com.casic.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.net.Socket; +import java.net.UnknownHostException; + +@Component +public class ServerSocketUtil { + + @Value("${casic.host}") + private String host; + @Value("${casic.port}") + private Integer port; + + public String sendMsg(String Json) throws UnknownHostException, IOException { + + // 向服务器端发送请求,服务器IP地址和服务器监听的端口号 + Socket server = new Socket(host, port); + if(!server.isConnected()){ + return "11"; + } + + OutputStream os = server.getOutputStream(); + //把输出流封装在DataOutputStream中 + DataOutputStream dos = new DataOutputStream(os); + //使用writeUTF发送字符串 + dos.writeUTF("Legendary!"); + dos.flush(); + dos.close(); + server.close(); +// System.out.println("连接已建立..."); +// // 发送消息 +// printWriter.println(Json); +// printWriter.flush(); + return "200"; + } + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..9d9f8a7 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,20 @@ +server: + port: 11642 +################### spring配置 ################### +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://111.198.10.15:11102/smartwell_br_test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8&&allowMultiQueries=true + username: root + password: Casic203! + session: + store-type: redis + jms: + pub-sub-domain: true + +logging: + level.root: info + level.com.casic: info + file: + path: logs/ + name: missiles.log \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..f1e2c28 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,33 @@ +########################################################## +################## 所有profile共有的配置 ################# +########################################################## +spring: + profiles: + active: dev + servlet: + multipart: + max-file-size: 50MB + max-request-size: 80MB +mybatis-plus: + global-config: + enable-sql-runner: true + configuration: + # 配置结果集属性为空时 是否映射返回结果 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用 + mapper-locations: classpath:mapper/**/*.xml,classpath:com/casic/dao/mapper/**/*.xml +#mybatis: +# mapper-locations: classpath:mapper/*.xml +#mybatis-plus: +# sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector +casic: + device: + gas-dector: + type: 101 + minutes: 60 + enable-local: false + host: 127.0.0.1 + port: 11320 + url: http://127.0.0.1:1164/test + +# type 可燃气体的设备类型 +# minutes: 燃气外协设备上传数据的分钟数 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84ba3e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Default ignored files +/target/ +/logs/ +/.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..279de1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,158 @@ + + + 4.0.0 + + com.casic + data-forwarding + 1.0-SNAPSHOT + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + 2.1.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-jdbc + 2.1.3.RELEASE + + + + mysql + mysql-connector-java + 8.0.16 + compile + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.3 + + + + org.postgresql + postgresql + 42.2.19 + + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + + org.projectlombok + lombok + 1.18.20 + + + + io.netty + netty-all + 4.1.100.Final + + + + + com.alibaba + druid + 1.2.6 + + + + com.alibaba + fastjson + 2.0.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE + + true + + com.casic.CasicApplication + exec + + + + + repackage + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + false + + + + + + + src/main/resources + + + /config/*/* + /config/*-*.yml + + true + + + src/main/resources + + **/*.xml + + true + + + src/main/java + + **/*.xml + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/com/casic/CasicApplication.java b/src/main/java/com/casic/CasicApplication.java new file mode 100644 index 0000000..d31b7fc --- /dev/null +++ b/src/main/java/com/casic/CasicApplication.java @@ -0,0 +1,23 @@ +package com.casic; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * SpringBoot方式启动类 + * + * @author cz + * @Date 2022/06/20 14:28 + */ + +@Slf4j +@ComponentScan(basePackages= "com.casic.**") +@SpringBootApplication +public class CasicApplication { + public static void main(String[] args) { + log.info("CasicApplication is success!"); + SpringApplication.run(CasicApplication.class, args); + } +} diff --git a/src/main/java/com/casic/common/CasicFrame.java b/src/main/java/com/casic/common/CasicFrame.java new file mode 100644 index 0000000..02e704b --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrame.java @@ -0,0 +1,25 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CasicFrame { + + final String HEADER = "AA"; + final String TAIL = "FF"; + + String version; + int length; + String deviceId; + String deviceType; + String messageType; + String sequence; + String control; + String uptime; + JSONObject messageBody; + + public void parseMessageBody() { + + } +} diff --git a/src/main/java/com/casic/common/CasicFrameBuildFactory.java b/src/main/java/com/casic/common/CasicFrameBuildFactory.java new file mode 100644 index 0000000..123062e --- /dev/null +++ b/src/main/java/com/casic/common/CasicFrameBuildFactory.java @@ -0,0 +1,81 @@ +package com.casic.common; + +import com.casic.tube.frame.HeartFrame; +import com.casic.tube.frame.brs.DataFrameBRS; +import com.casic.tube.frame.brs.EventFrameBRS; +import com.casic.tube.frame.brs.InfoFrameBRS; +import com.casic.tube.frame.IMEIFrame; +import com.casic.tube.frame.mhk.DataFrameMHK; +import com.casic.tube.frame.mhk.EventFrameMHK; +import com.casic.tube.frame.mhk.InfoFrameMHK; +import com.casic.tube.frame.tp.DataFrameHTTP; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CasicFrameBuildFactory { + + public static CasicFrame buildCasicFrame(String messageType, String manufacturerCode) { + switch (messageType) { + case "00": + return new HeartFrame(); + + case "01": + return buildEventFrame(manufacturerCode); + + case "02": + return buildDataFrame(manufacturerCode); + + case "05": + return new IMEIFrame(); + + case "07": + return buildInfoFrame(manufacturerCode); + + default: + log.warn("上行消息类型不在范围内[" + messageType + "]"); + return null; + } + } + + private static CasicFrame buildDataFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": // 百瑞生 + return new DataFrameBRS(); + + case "16": // 麦哈克 + return new DataFrameMHK(); + + case "17": // 航天拓扑 + return new DataFrameHTTP(); + + default: + return null; + } + } + + private static CasicFrame buildEventFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "15": + return new EventFrameBRS(); + + case "16": + return new EventFrameMHK(); + + default: + return null; + } + } + + private static CasicFrame buildInfoFrame(String manufacturerCode) { + switch (manufacturerCode) { + case "14": + return new InfoFrameMHK(); + + case "15": + return new InfoFrameBRS(); + + default: + return null; + } + } +} diff --git a/src/main/java/com/casic/common/CasicProtocol.java b/src/main/java/com/casic/common/CasicProtocol.java new file mode 100644 index 0000000..1b2c6fd --- /dev/null +++ b/src/main/java/com/casic/common/CasicProtocol.java @@ -0,0 +1,22 @@ +package com.casic.common; + +import com.alibaba.fastjson.JSONObject; + +public interface CasicProtocol { + + public boolean checkFrame(String frame); + + public String getDeviceId(String frame); + public String getManufacturerCode(String frame); + + public String getDeviceType(String frame); + + public String getMessageType(String frame); + + public String getMessageBody(String frame); + + public JSONObject parseMessageBody(String messageBody); + + public String getUptime(String frame); + +} diff --git a/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java new file mode 100644 index 0000000..a4842ab --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DataTubeOtherMapper.java @@ -0,0 +1,18 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DataTubeOther; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DataTubeOtherMapper extends BaseMapper { + +} diff --git a/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java new file mode 100644 index 0000000..1d73134 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/DeviceWellViewMapper.java @@ -0,0 +1,20 @@ +package com.casic.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.dao.model.DeviceWellView; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 报警数据 Mapper 接口 + *

+ * + * @author cz + * @since 2023-11-20 + */ +@Mapper +public interface DeviceWellViewMapper extends BaseMapper { + + DeviceWellView getOneByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml new file mode 100644 index 0000000..27643b7 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DataTubeOtherMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + id, DEVCODE, WELL_CODE, GASVAL, UPTIME, LOGTIME + + + + ${paramStr} + + + + TO_TIMESTAMP(${paramStr},'yyyy-MM-dd hh24:mi:ss')::timestamp without time zone + + + + TO_DATE(${paramStr},'yyyy-mm-dd hh24:mi') + + + diff --git a/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml new file mode 100644 index 0000000..58d5b87 --- /dev/null +++ b/src/main/java/com/casic/dao/mapper/mapping/DeviceWellViewMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + id, devcode, deviceName, deviceType, wellCode, wellName + + + + + diff --git a/src/main/java/com/casic/dao/model/DataTubeOther.java b/src/main/java/com/casic/dao/model/DataTubeOther.java new file mode 100644 index 0000000..8069f36 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DataTubeOther.java @@ -0,0 +1,96 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("data_tube_other") +public class DataTubeOther implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("ID") + private Long id; + + /** + * 设备编号 + */ + @TableField("DEVCODE") + private String devcode; + + /** + * 点位编号 + */ + @TableField("WELL_CODE") + private String wellCode; + + + /** + * 气体浓度采样值 + */ + @TableField("GASVAL") + private String gasval; + + /** + * 设备电池电压值(毫伏) + */ + @TableField("VBAT") + private String vbat; + + /** + * 电池状态0 正常、 1 低电告警、2 关机 + */ + @TableField("BATSTA") + private String batsta; + + /** + * 接收信号强度等级 + */ + @TableField("SIN") + private String sin; + + /** + * 接收信号参考质量 服务小 区的 RSRP 值 + */ + @TableField("RSRP") + private String rsrp; + + /** + * 信噪比 + */ + @TableField("SINR") + private String sinr; + + /** + * 采集时间 + */ + @TableField("UPTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime uptime; + + /** + * 上传时间 默认为当前时间 + */ + @TableField("LOGTIME") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime logtime; + + +} diff --git a/src/main/java/com/casic/dao/model/DeviceWellView.java b/src/main/java/com/casic/dao/model/DeviceWellView.java new file mode 100644 index 0000000..be247c9 --- /dev/null +++ b/src/main/java/com/casic/dao/model/DeviceWellView.java @@ -0,0 +1,62 @@ +package com.casic.dao.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 第三方厂家管盯数据 + *

+ * + * @author tanyue + * @since 2024-07-01 + */ +@Data +@TableName("device_well_view") +public class DeviceWellView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId("id") + private Long id; + + /** + * 设备编号 + */ + @TableField("devcode") + private String devcode; + + /** + * 设备名称 + */ + @TableField("deviceName") + private String deviceName; + + /** + * 设备类型(字典值) + */ + @TableField("deviceType") + private String deviceType; + + /** + * 点位编号 + */ + @TableField("wellCode") + private String wellCode; + + /** + * 点位编号 + */ + @TableField("wellName") + private String wellName; + +} diff --git a/src/main/java/com/casic/dao/service/IDataTubeOtherService.java b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java new file mode 100644 index 0000000..3d174d0 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDataTubeOtherService.java @@ -0,0 +1,8 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; + +public interface IDataTubeOtherService extends IService { + +} diff --git a/src/main/java/com/casic/dao/service/IDeviceWellViewService.java b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java new file mode 100644 index 0000000..d6b1200 --- /dev/null +++ b/src/main/java/com/casic/dao/service/IDeviceWellViewService.java @@ -0,0 +1,10 @@ +package com.casic.dao.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; + +public interface IDeviceWellViewService extends IService { + + DeviceWellView getDeviceWellViewByDevCode(String devCode); +} diff --git a/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java new file mode 100644 index 0000000..649ab90 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DataTubeOtherServiceImpl.java @@ -0,0 +1,11 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DataTubeOtherMapper; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.service.IDataTubeOtherService; +import org.springframework.stereotype.Service; + +@Service +public class DataTubeOtherServiceImpl extends ServiceImpl implements IDataTubeOtherService { +} diff --git a/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java new file mode 100644 index 0000000..f30d824 --- /dev/null +++ b/src/main/java/com/casic/dao/service/impl/DeviceWellViewServiceImpl.java @@ -0,0 +1,15 @@ +package com.casic.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.dao.mapper.DeviceWellViewMapper; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDeviceWellViewService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceWellViewServiceImpl extends ServiceImpl implements IDeviceWellViewService { + @Override + public DeviceWellView getDeviceWellViewByDevCode(String devCode) { + return baseMapper.getOneByDevCode(devCode); + } +} diff --git a/src/main/java/com/casic/service/MyChannelHandlerPool.java b/src/main/java/com/casic/service/MyChannelHandlerPool.java new file mode 100644 index 0000000..9ab8fae --- /dev/null +++ b/src/main/java/com/casic/service/MyChannelHandlerPool.java @@ -0,0 +1,19 @@ +package com.casic.service; + +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + +/** + * MyChannelHandlerPool + * 通道组池,管理所有websocket连接 + * @author zhengkai.blog.csdn.net + * @date 2019-06-12 + */ +public class MyChannelHandlerPool { + + public MyChannelHandlerPool(){} + + public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/MyWebSocketHandler.java b/src/main/java/com/casic/service/MyWebSocketHandler.java new file mode 100644 index 0000000..e4d174e --- /dev/null +++ b/src/main/java/com/casic/service/MyWebSocketHandler.java @@ -0,0 +1,82 @@ +package com.casic.service; + +import com.alibaba.fastjson.JSON; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.HashMap; +import java.util.Map; + +public class MyWebSocketHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端建立连接,通道开启!"); + + //添加到channelGroup通道组 + MyChannelHandlerPool.channelGroup.add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("与客户端断开连接,通道关闭!"); + //添加到channelGroup 通道组 + MyChannelHandlerPool.channelGroup.remove(ctx.channel()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //首次连接是FullHttpRequest,处理参数 by zhengkai.blog.csdn.net + if (null != msg && msg instanceof FullHttpRequest) { + FullHttpRequest request = (FullHttpRequest) msg; + String uri = request.uri(); + Map paramMap=getUrlParams(uri); + System.out.println("接收到的参数是:"+ JSON.toJSONString(paramMap)); + //如果url包含参数,需要处理 + if(uri.contains("?")){ + String newUri=uri.substring(0,uri.indexOf("?")); + System.out.println(newUri); + request.setUri(newUri); + } + + }else if(msg instanceof TextWebSocketFrame){ + //正常的TEXT消息类型 + TextWebSocketFrame frame=(TextWebSocketFrame)msg; + System.out.println("客户端收到服务器数据:" +frame.text()); + sendAllMessage(frame.text()); + } + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception { + + } + + private void sendAllMessage(String message){ + //收到信息后,群发给所有channel + MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message)); + } + + private static Map getUrlParams(String url){ + Map map = new HashMap<>(); + url = url.replace("?",";"); + if (!url.contains(";")){ + return map; + } + if (url.split(";").length > 0){ + String[] arr = url.split(";")[1].split("&"); + for (String s : arr){ + String key = s.split("=")[0]; + String value = s.split("=")[1]; + map.put(key,value); + } + return map; + + }else{ + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/service/NettyServer.java b/src/main/java/com/casic/service/NettyServer.java new file mode 100644 index 0000000..aa56093 --- /dev/null +++ b/src/main/java/com/casic/service/NettyServer.java @@ -0,0 +1,58 @@ +package com.casic.service; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; + +/** + * NettyServer Netty服务器配置 + */ +public class NettyServer { + private final int port; + + public NettyServer(int port) { + this.port = port; + } + + public void start() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + + EventLoopGroup group = new NioEventLoopGroup(); + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.option(ChannelOption.SO_BACKLOG, 1024); + sb.group(group, bossGroup) // 绑定线程池 + .channel(NioServerSocketChannel.class) // 指定使用的channel + .localAddress(this.port)// 绑定监听端口 + .childHandler(new ChannelInitializer() { // 绑定客户端连接时候触发操作 + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + System.out.println("收到新连接"); + //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 + ch.pipeline().addLast(new HttpServerCodec()); + //以块的方式来写的处理器 + ch.pipeline().addLast(new ChunkedWriteHandler()); + ch.pipeline().addLast(new HttpObjectAggregator(8192)); + ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10)); + ch.pipeline().addLast(new MyWebSocketHandler()); + } + }); + ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定 + System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress()); + cf.channel().closeFuture().sync(); // 关闭服务器通道 + } finally { + group.shutdownGracefully().sync(); // 释放线程池资源 + bossGroup.shutdownGracefully().sync(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/tube/controller/TubeDataRecvController.java b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java new file mode 100644 index 0000000..07cc972 --- /dev/null +++ b/src/main/java/com/casic/tube/controller/TubeDataRecvController.java @@ -0,0 +1,67 @@ +package com.casic.tube.controller; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.tube.service.ITubeDataService; +import com.casic.tube.service.TubeDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.Base64; +import java.util.Map; + +@Slf4j +@RestController +public class TubeDataRecvController { + + @Resource + private ITubeDataService tubeDataService; + + @RequestMapping("/tube/data/recv") + public String dataRecv(@RequestBody Map map) { + JSONObject retObj = new JSONObject(); + log.info(JSONObject.toJSONString(map)); + + JSONObject recvObj = (JSONObject) JSONObject.toJSON(map); + if (recvObj.containsKey("payload")) { + JSONObject payload = recvObj.getJSONObject("payload"); + String value = ""; + if (payload.containsKey("APPdata")) { + value = payload.getString("APPdata"); + } else if (payload.containsKey("serviceData")) { + JSONObject serviceData = payload.getJSONObject("serviceData"); + value = serviceData.getString("Value"); + } + + log.info(value); + + if (value.isEmpty()) { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } else { + byte[] baseBytes = Base64.getDecoder().decode(value); + String frameStr = new String(baseBytes); + + // 根据协议进行解析 + CasicFrame frame = tubeDataService.dataParse(frameStr); + + // 存库 + tubeDataService.afterAction(frame); + + retObj.put("code", 200); + retObj.put("success", true); + } + } else { + retObj.put("resp", "payload not matched"); + retObj.put("code", 200); + retObj.put("success", false); + } + + return retObj.toJSONString(); + } +} diff --git a/src/main/java/com/casic/tube/frame/DataFrame.java b/src/main/java/com/casic/tube/frame/DataFrame.java new file mode 100644 index 0000000..5414329 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/DataFrame.java @@ -0,0 +1,13 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import com.casic.dao.model.DataTubeOther; + +import java.util.List; + +public class DataFrame extends CasicFrame { + + public List toDataModelList() { + return null; + } +} diff --git a/src/main/java/com/casic/tube/frame/HeartFrame.java b/src/main/java/com/casic/tube/frame/HeartFrame.java new file mode 100644 index 0000000..fbeb2d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/HeartFrame.java @@ -0,0 +1,16 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class HeartFrame extends CasicFrame { + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "上报时间: " + getUptime(); + } +} diff --git a/src/main/java/com/casic/tube/frame/IMEIFrame.java b/src/main/java/com/casic/tube/frame/IMEIFrame.java new file mode 100644 index 0000000..cf951c2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/IMEIFrame.java @@ -0,0 +1,27 @@ +package com.casic.tube.frame; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class IMEIFrame extends CasicFrame { + + String imei; + String iccid; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "IMEI: " + imei + "; " + + "ICCID: " + iccid + "; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + imei = getMessageBody().getString("IMEI"); + iccid = getMessageBody().getString("ICCID"); + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java new file mode 100644 index 0000000..110f11b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataFrameBRS.java @@ -0,0 +1,72 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameBRS extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemBRS dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemBRS dataItem = new DataItemBRS(); + + dataItem.setGas(String.valueOf(Double.parseDouble(dataObj.getString("GAS")) * 0.01)); + dataItem.setBat(dataObj.getString("BAT")); + dataItem.setSig(dataObj.getString("SIG")); + dataItem.setTemp(String.valueOf(Double.parseDouble(dataObj.getString("TEMP")))); + dataItem.setSsState(dataObj.getString("SSSTATE")); + dataItem.setDevStat(dataObj.getString("DEVSTAT")); + dataItem.setTime(dataObj.getString("UPTIME")); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemBRS dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(dataItem.getGas()); + data.setVbat(dataItem.getBat()); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java new file mode 100644 index 0000000..1ed89af --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/DataItemBRS.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class DataItemBRS { + String sig; // 信号强度:0表示无信号,1表示信号弱,2表示信号中等,3表示信号强 + String temp; // 温度值 + String ssState; // 传感器状态:0表示正常,39表示传感器通讯异常 + String bat; // 电池电压 单位mv + String gas; // 浓度,单位%VOL + String devStat; // 设备状态,0表示正常,其他值表示异常 + String time; // 采集时间 + + @Override + public String toString() { + return "气体浓度值: " + gas + " %VOL; " + + "电池电压值: " + bat + " 毫伏; " + + "设备状态: " + devStat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java new file mode 100644 index 0000000..fc6c14b --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventFrameBRS.java @@ -0,0 +1,47 @@ +package com.casic.tube.frame.brs; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameBRS extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemBRS eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]; "); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemBRS eventItem = new EventItemBRS(); + + eventItem.setEventType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java new file mode 100644 index 0000000..fb712cb --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/EventItemBRS.java @@ -0,0 +1,17 @@ +package com.casic.tube.frame.brs; + +import lombok.Data; + +@Data +public class EventItemBRS { + String eventType; + String value; + String time; + + @Override + public String toString() { + return "报警类型: " + eventType + "; " + + "报警数值: " + value + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java new file mode 100644 index 0000000..1bb6664 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/brs/InfoFrameBRS.java @@ -0,0 +1,125 @@ +package com.casic.tube.frame.brs; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameBRS extends CasicFrame { + + String workmode; // 工作模式 + String model; // 型号 + String softVersion; // 软件版本 + String hwVersion; // 硬件版本 + String sensorType; // 传感器类型 + String simcard; // SIM卡号 + String imei; // IMEI号 + + String rsrp; // 信号接收功率 + String rsrq; // 信号接收质量 + String cellId; // 服务小区ID + String rssi; // 信号强度指示 + String signalECL; // 信号增强覆盖等级 + String sinr; // 信噪比 + String pci; // 服务小区物理小区识别码 + + String gasL; // 浓度低报阈值,单位为%VOL,实际传输时扩大100倍 + String gasH; // 浓度高报阈值,单位为%VOL,实际传输时扩大100倍 + String slope; // 浓度梯度阈值,单位为%VOL,如果设备检测到浓度并报警后,后续每上涨slope%VOL才会生成一次报警 + String tempL; // 温度低限阈值,扩大100倍 + String tempH; // 温度高限阈值,扩大100倍 + String bat; // 电池电压,单位mV + String sampleIntvl; // 采样间隔,单位秒 + String sampleCnt; // 采样点数,达到采样点数上传数据 + String preheatTim; // 传感器预热时间,仅针对催化传感器有效 + + String shakeEn; // 振动功能使能 + String shakeSampleEn; // 振动采样功能使能 + String shake1; // 振动阈值1 + String shake2; // 振动阈值2 + String antitheftEn; // 位移功能使能 + String liquidLevelEn; // 液位功能使能 + + String pressEn; // 压力采集使能 + String accThrld; // 加速度阈值1 + String accCnt; // 加速度阈值2 + String preRange; // 压力表量程,单位kPa,扩大100倍传输 + String preAlarmEn; // 压力报警使能 + String preK; // 压力修正系数k + String preB; // 压力修正系数b + String preH; // 压力高报阈值,单位kPa,扩大100倍传输 + String preL; // 压力低报阈值,单位kPa,扩大100倍传输 + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + (softVersion == null || softVersion.isEmpty() ? "" : "软件版本: " + softVersion + "; ") + + (simcard == null || simcard.isEmpty() ? "" : "SIM卡号: " + simcard + "; ") + + (rsrp == null || rsrp.isEmpty() ? "" : ("信号接收功率: " + rsrp) + "; ") + + (gasL == null || gasH == null || gasL.isEmpty() || gasH.isEmpty() ? "" : "浓度报警阈值(%VOL): " + Double.parseDouble(gasL) * 0.01 + ", " + Double.parseDouble(gasH) * 0.01 + "; ") + + (slope == null || slope.isEmpty() ? "" : "浓度梯度阈值(%VOL): " + Double.parseDouble(slope) * 0.01 + "; ") + + (bat == null || bat.isEmpty() ? "" : "电池电压: " + bat + " mv;") + + (antitheftEn == null || antitheftEn.isEmpty() ? "" : "位移功能: " + (antitheftEn.equals("1") ? "有效" : "无效") + "; ") + + (liquidLevelEn == null || liquidLevelEn.isEmpty() ? "" : "液位功能: " + (liquidLevelEn.equals("1") ? "有效" : "无效") + "; ") + + (pressEn == null || pressEn.isEmpty() ? "" : "压力采集功能: " + (pressEn.equals("1") ? "有效" : "无效") + "; ") + + (preL == null || preH == null || preL.isEmpty() || preH.isEmpty() ? "" : "压力报警阈值(Kpa): " + Double.parseDouble(preL) * 0.01 + ", " + Double.parseDouble(preH) * 0.01 + "; ") + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + if (getMessageBody().containsKey("WORKMODE")) { + workmode = getMessageBody().getString("WORKMODE"); + model = getMessageBody().getString("MODEL"); + hwVersion = getMessageBody().getString("HWVERSION"); + softVersion = getMessageBody().getString("SOFTVERSION"); + sensorType = getMessageBody().getString("SENSORTYPE"); + simcard = getMessageBody().getString("SIMCARD"); + imei = getMessageBody().getString("IMEI"); + } + + if (getMessageBody().containsKey("RSRP")) { + rsrp = getMessageBody().getString("RSRP"); + rsrq = getMessageBody().getString("RSRP"); + cellId = getMessageBody().getString("CELLID"); + rssi = getMessageBody().getString("RSSI"); + signalECL = getMessageBody().getString("SIGNALECL"); + sinr = getMessageBody().getString("SINR"); + pci = getMessageBody().getString("PCI"); + } + + if (getMessageBody().containsKey("GASL")) { + gasL = getMessageBody().getString("GASL"); + gasH = getMessageBody().getString("GASH"); + slope = getMessageBody().getString("SLOPE"); + tempL = getMessageBody().getString("TEMPL"); + tempH = getMessageBody().getString("TEMPH"); + bat = getMessageBody().getString("BAT"); + sampleIntvl = getMessageBody().getString("SAMPLEINTVL"); + sampleCnt = getMessageBody().getString("SAMPLECNT"); + preheatTim = getMessageBody().getString("PREHEATTIM"); + } + + if (getMessageBody().containsKey("SHAKEEN")) { + shakeEn = getMessageBody().getString("SHAKEEN"); + shakeSampleEn = getMessageBody().getString("SHAKESAMPLEEN"); + shake1 = getMessageBody().getString("SHAKE1"); + shake2 = getMessageBody().getString("SHAKE2"); + antitheftEn = getMessageBody().getString("ANTITHEFTEN"); + liquidLevelEn = getMessageBody().getString("LIQUIDLEVELEN"); + } + + if (getMessageBody().containsKey("PRESSEN")) { + pressEn = getMessageBody().getString("PRESSEN"); + accThrld = getMessageBody().getString("ACCTHRLD"); + accCnt = getMessageBody().getString("ACCCNT"); + preRange = getMessageBody().getString("PRERANGE"); + preAlarmEn = getMessageBody().getString("PREALARMEN"); + preK = getMessageBody().getString("PREK"); + preB = getMessageBody().getString("PREB"); + preH = getMessageBody().getString("PREH"); + preL = getMessageBody().getString("PREL"); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java new file mode 100644 index 0000000..199fa25 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataFrameMHK.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameMHK extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemMHK dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemMHK dataItem = new DataItemMHK(); + + dataItem.setGasval(Double.parseDouble(dataObj.getString("GASVAL"))); + dataItem.setVbat(Integer.parseInt(dataObj.getString("VBAT"))); + dataItem.setBatsta(dataObj.getString("BATSTA")); + dataItem.setTime(dataObj.getString("UPTIME")); + dataItem.setSin(Integer.parseInt(dataObj.getString("SIN"))); + dataItem.setRsrp(Integer.parseInt(dataObj.getString("RSRP"))); + dataItem.setSinr(Integer.parseInt(dataObj.getString("SINR"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemMHK dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getGasval())); + data.setVbat(String.valueOf(dataItem.getVbat())); + data.setSin(String.valueOf(dataItem.getSin())); + data.setRsrp(String.valueOf(dataItem.getRsrp())); + data.setSinr(String.valueOf(dataItem.getSinr())); + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java new file mode 100644 index 0000000..a6e25e2 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/DataItemMHK.java @@ -0,0 +1,22 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class DataItemMHK { + double gasval; + int vbat; + String batsta; + String time; + int sin; + int rsrp; + int sinr; + + @Override + public String toString() { + return "气体浓度值: " + gasval + "; " + + "电池电压值: " + vbat + " 毫伏; " + + "电池状态: " + batsta + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java new file mode 100644 index 0000000..793ffc0 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class EventFrameMHK extends CasicFrame { + + List eventItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (EventItemMHK eventItem : eventItemList) { + builder.append("["); + builder.append(eventItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray eventArray = getMessageBody().getJSONArray("DATAS"); + eventItemList = new ArrayList<>(); + for (int i = 0; i < eventArray.size(); i++) { + JSONObject dataObj = eventArray.getJSONObject(i); + EventItemMHK eventItem = new EventItemMHK(); + + eventItem.setType(dataObj.getString("EVENTTYPE")); + eventItem.setValue(dataObj.getString("VALUE")); + eventItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + eventItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + eventItem.setTime(dataObj.getString("UPTIME")); + + eventItemList.add(eventItem); + } + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java new file mode 100644 index 0000000..de2751f --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/EventItemMHK.java @@ -0,0 +1,20 @@ +package com.casic.tube.frame.mhk; + +import lombok.Data; + +@Data +public class EventItemMHK { + String type; + String value; + double lon; + double lat; + String time; + + @Override + public String toString() { + return "报警类型: " + type + "; " + + "报警数值: " + value + "; " + + "报警位置: " + lon + ", " + lat + "; " + + "报警时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java new file mode 100644 index 0000000..ae463d7 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/mhk/InfoFrameMHK.java @@ -0,0 +1,49 @@ +package com.casic.tube.frame.mhk; + +import com.casic.common.CasicFrame; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class InfoFrameMHK extends CasicFrame { + + String sv; + String hv; + int al; + int ah; + int intv; + int up; + double lon; + double lat; + int prt; + int gal; + int lbt; + + @Override + public String toString() { + return "设备编号: " + getDeviceId() + "; " + + "设备采样周期: " + intv + " 分钟; " + + "设备上传周期: " + up + " 分钟; " + + "设备报警阈值: " + al + ", " + ah + "; " + + "设备安装位置: " + lon + ", " + lat + "; " + + "GPS位移告警距离: " + gal + " 米; " + + "电池低报阈值: " + lbt + " 毫伏; " + + "上报时间: " + getUptime(); + } + + @Override + public void parseMessageBody() { + sv = getMessageBody().getString("SV"); + hv = getMessageBody().getString("HV"); + al = Integer.parseInt(getMessageBody().getString("AL")); + ah = Integer.parseInt(getMessageBody().getString("AH")); + intv = Integer.parseInt(getMessageBody().getString("INTV")); + up = Integer.parseInt(getMessageBody().getString("UP")); + lon = Double.parseDouble(getMessageBody().getString("LON")); + lat = Double.parseDouble(getMessageBody().getString("LAT")); + prt = Integer.parseInt(getMessageBody().getString("PRT")); + gal = Integer.parseInt(getMessageBody().getString("GAL")); + lbt = Integer.parseInt(getMessageBody().getString("LBV")); + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java new file mode 100644 index 0000000..1f38aab --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataFrameHTTP.java @@ -0,0 +1,74 @@ +package com.casic.tube.frame.tp; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.dao.model.DataTubeOther; +import com.casic.tube.frame.DataFrame; +import com.casic.tube.frame.mhk.DataItemMHK; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Data +@Slf4j +public class DataFrameHTTP extends DataFrame { + + List dataItemList; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("设备编号: ").append(getDeviceId()).append("; "); + for (DataItemHTTP dataItem : dataItemList) { + builder.append("["); + builder.append(dataItem); + builder.append("]"); + } + builder.append("上报时间: ").append(getUptime()); + return builder.toString(); + } + + @Override + public void parseMessageBody() { + JSONArray dataArray = getMessageBody().getJSONArray("DATAS"); + dataItemList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObj = dataArray.getJSONObject(i); + DataItemHTTP dataItem = new DataItemHTTP(); + + dataItem.setCh4(Integer.parseInt(dataObj.getString("CH4"))); + dataItem.setVbat(Double.parseDouble(dataObj.getString("VBAT"))); + dataItem.setTemp(Double.parseDouble(dataObj.getString("TEMP"))); + dataItem.setRh(Double.parseDouble(dataObj.getString("RH"))); + dataItem.setTime(dataObj.getString("CT")); + dataItem.setSig(Integer.parseInt(dataObj.getString("SIG"))); + dataItem.setAlarm(Integer.parseInt(dataObj.getString("ALARM"))); + dataItem.setLon(Double.parseDouble(dataObj.getString("LON"))); + dataItem.setLat(Double.parseDouble(dataObj.getString("LAT"))); + + dataItemList.add(dataItem); + } + } + + @Override + public List toDataModelList() { + List dataList = new ArrayList<>(); + for (DataItemHTTP dataItem : dataItemList) { + DataTubeOther data = new DataTubeOther(); + + data.setDevcode(getDeviceId()); + data.setGasval(String.valueOf(dataItem.getCh4())); + data.setVbat(String.valueOf(dataItem.getVbat() * 1000)); // 单位转换为mv + data.setUptime(LocalDateTime.parse(dataItem.getTime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 采集时间 + data.setLogtime(LocalDateTime.parse(getUptime(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 上报时间 + + dataList.add(data); + } + + return dataList; + } +} diff --git a/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java new file mode 100644 index 0000000..9a53bd5 --- /dev/null +++ b/src/main/java/com/casic/tube/frame/tp/DataItemHTTP.java @@ -0,0 +1,26 @@ +package com.casic.tube.frame.tp; + +import lombok.Data; + +@Data +public class DataItemHTTP { + int ch4; // 甲烷浓度值(ppm) + double temp; // 温度值(℃) + double rh; // 湿度值(%) + double vbat; // 电池电压V + double lon; // 经度 + double lat; // 纬度 + String time; // 采集时间 + int sig; // 信号强度 + int alarm; // 报警码 + + @Override + public String toString() { + return "甲烷浓度值: " + ch4 + " ppm; " + + "电池电压值: " + vbat + " V; " + + "温湿度: " + temp + " ℃, " + rh + " %; " + + "报警码: " + alarm + "; " + + "位置: " + lon + ", " + lat + "; " + + "采样时间: " + time; + } +} diff --git a/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java new file mode 100644 index 0000000..9efc23b --- /dev/null +++ b/src/main/java/com/casic/tube/protocol/CasicTubeProtocolImpl.java @@ -0,0 +1,65 @@ +package com.casic.tube.protocol; + +import com.alibaba.fastjson.JSONObject; +import com.casic.common.CasicProtocol; +import org.springframework.stereotype.Component; + +@Component +public class CasicTubeProtocolImpl implements CasicProtocol { + @Override + public boolean checkFrame(String frame) { + boolean valid = checkFrameHeaderAndTail(frame); + if (valid) { + valid = checkFrameLength(frame); + } + + return valid; + } + + private boolean checkFrameHeaderAndTail(String frame) { + return (frame.substring(0, 2).equalsIgnoreCase("AA")) && + (frame.substring(frame.length() - 2).equalsIgnoreCase("FF")); + } + + private boolean checkFrameLength(String frame) { + String lengthStr = frame.substring(4, 7); + int length = Integer.parseInt(lengthStr); + + return frame.length() == length + 9; + } + + @Override + public String getDeviceType(String frame) { + return frame.substring(7, 9); + } + + @Override + public String getDeviceId(String frame) { + return frame.substring(9, 21); + } + + @Override + public String getManufacturerCode(String frame) { + return frame.substring(11, 13); + } + + @Override + public String getMessageType(String frame) { + return frame.substring(21, 23); + } + + @Override + public String getMessageBody(String frame) { + return frame.substring(26, frame.length() - 16); + } + + @Override + public JSONObject parseMessageBody(String messageBody) { + return JSONObject.parseObject(messageBody); + } + + @Override + public String getUptime(String frame) { + return frame.substring(frame.length() - 16, frame.length() - 2); + } +} diff --git a/src/main/java/com/casic/tube/service/ITubeDataService.java b/src/main/java/com/casic/tube/service/ITubeDataService.java new file mode 100644 index 0000000..bc6af02 --- /dev/null +++ b/src/main/java/com/casic/tube/service/ITubeDataService.java @@ -0,0 +1,10 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; + +public interface ITubeDataService { + + public CasicFrame dataParse(String frame); + + public void afterAction(CasicFrame frame); +} diff --git a/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java new file mode 100644 index 0000000..25a9d12 --- /dev/null +++ b/src/main/java/com/casic/tube/service/TubeDataServiceImpl.java @@ -0,0 +1,84 @@ +package com.casic.tube.service; + +import com.casic.common.CasicFrame; +import com.casic.common.CasicFrameBuildFactory; +import com.casic.common.CasicProtocol; +import com.casic.dao.model.DataTubeOther; +import com.casic.dao.model.DeviceWellView; +import com.casic.dao.service.IDataTubeOtherService; +import com.casic.dao.service.IDeviceWellViewService; +import com.casic.tube.frame.DataFrame; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + + +@Service +@Slf4j +public class TubeDataServiceImpl implements ITubeDataService { + + @Resource + private CasicProtocol tubeProtocol; + + @Resource + IDataTubeOtherService tubeDataService; + + @Resource + IDeviceWellViewService deviceService; + + public CasicFrame dataParse(String frame) { + // 1. 判断帧结构 + boolean frameValid = tubeProtocol.checkFrame(frame); + if (frameValid) { + // 2. 获取帧结构中的关键字段信息 + String deviceId = tubeProtocol.getDeviceId(frame); + String messageType = tubeProtocol.getMessageType(frame); + String messageBody = tubeProtocol.getMessageBody(frame).toUpperCase(); + String uptime = tubeProtocol.getUptime(frame); + + String manufacturerCode = tubeProtocol.getManufacturerCode(frame); + CasicFrame tubeFrame = CasicFrameBuildFactory.buildCasicFrame(messageType, manufacturerCode); + + if (tubeFrame != null) { + tubeFrame.setDeviceId(deviceId); + tubeFrame.setUptime(uptime); + tubeFrame.setMessageType(messageType); + + // 心跳类的消息不解析MessageBody + if (!tubeFrame.getMessageType().equals("00")) { + tubeFrame.setMessageBody(tubeProtocol.parseMessageBody(messageBody)); + tubeFrame.parseMessageBody(); + } + + log.info(tubeFrame.toString()); + return tubeFrame; + } + } else { + log.error("消息帧解析异常"); + } + + return null; + } + + @Override + public void afterAction(CasicFrame frame) { + // 数据消息帧 进行存库操作 + if (frame instanceof DataFrame) { + String devCode = frame.getDeviceId(); + DeviceWellView devWellView = deviceService.getDeviceWellViewByDevCode(devCode); + String wellCode = ""; + if (devWellView != null) { + wellCode = devWellView.getWellCode(); + } + List dataList = ((DataFrame) frame).toDataModelList(); + if (dataList != null) { + for (DataTubeOther data : dataList) { + data.setWellCode(wellCode); + tubeDataService.save(data); + } + } + } + } +} diff --git a/src/main/java/com/casic/util/Client.java b/src/main/java/com/casic/util/Client.java new file mode 100644 index 0000000..7aeb2e1 --- /dev/null +++ b/src/main/java/com/casic/util/Client.java @@ -0,0 +1,34 @@ +package com.casic.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 客户端socket + */ +public class Client { + public static void main(String[] args) { + try { + //发送到8888端口 + Socket socket = new Socket("127.0.0.1", 11321); + //输出流 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("服务端你好,我是客户端"); + printWriter.flush(); + //关闭资源 + printWriter.close(); + outputStream.close(); + socket.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/casic/util/HttpClientUtil.java b/src/main/java/com/casic/util/HttpClientUtil.java new file mode 100644 index 0000000..ca92b11 --- /dev/null +++ b/src/main/java/com/casic/util/HttpClientUtil.java @@ -0,0 +1,141 @@ +package com.casic.util; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class HttpClientUtil { + + public static String doGet(String url, Map param) { + + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 + if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return resultString; + } + + public static String doPost(String url) { + return doPost(url, null); + } + + public static String doPostJson(String json, String url) throws Exception { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setSocketTimeout(3000) + .setConnectTimeout(3000) + .build(); + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception ex) { + throw ex; + } finally { + if (null != response) { + response.close(); + } + if (null != httpClient) { + httpClient.close(); + } + } + + return resultString; + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/Server.java b/src/main/java/com/casic/util/Server.java new file mode 100644 index 0000000..327da37 --- /dev/null +++ b/src/main/java/com/casic/util/Server.java @@ -0,0 +1,38 @@ +package com.casic.util; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author: njb + * @Date: 2020/11/26 18:49 + * @desc: 服务器socket + */ +public class Server { + public static void main(String[] args) { + try { + ServerSocket serverSocket = new ServerSocket(11321); + System.out.println("----------------服务端执行,開始监听请求----------------"); + + Socket socket = serverSocket.accept();//開始监听 + InputStream inputStream = socket.getInputStream(); + //获取请求内容 + String info; + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((info = bufferedReader.readLine()) != null) { + System.out.println("我是服务端,客户端请求为:" + info); + } + //关闭资源 + socket.shutdownInput(); + bufferedReader.close(); + inputStream.close(); + socket.close(); + serverSocket.close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/ServerSocketUtil.java b/src/main/java/com/casic/util/ServerSocketUtil.java new file mode 100644 index 0000000..830aca0 --- /dev/null +++ b/src/main/java/com/casic/util/ServerSocketUtil.java @@ -0,0 +1,41 @@ +package com.casic.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.net.Socket; +import java.net.UnknownHostException; + +@Component +public class ServerSocketUtil { + + @Value("${casic.host}") + private String host; + @Value("${casic.port}") + private Integer port; + + public String sendMsg(String Json) throws UnknownHostException, IOException { + + // 向服务器端发送请求,服务器IP地址和服务器监听的端口号 + Socket server = new Socket(host, port); + if(!server.isConnected()){ + return "11"; + } + + OutputStream os = server.getOutputStream(); + //把输出流封装在DataOutputStream中 + DataOutputStream dos = new DataOutputStream(os); + //使用writeUTF发送字符串 + dos.writeUTF("Legendary!"); + dos.flush(); + dos.close(); + server.close(); +// System.out.println("连接已建立..."); +// // 发送消息 +// printWriter.println(Json); +// printWriter.flush(); + return "200"; + } + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..9d9f8a7 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,20 @@ +server: + port: 11642 +################### spring配置 ################### +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://111.198.10.15:11102/smartwell_br_test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8&&allowMultiQueries=true + username: root + password: Casic203! + session: + store-type: redis + jms: + pub-sub-domain: true + +logging: + level.root: info + level.com.casic: info + file: + path: logs/ + name: missiles.log \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..f1e2c28 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,33 @@ +########################################################## +################## 所有profile共有的配置 ################# +########################################################## +spring: + profiles: + active: dev + servlet: + multipart: + max-file-size: 50MB + max-request-size: 80MB +mybatis-plus: + global-config: + enable-sql-runner: true + configuration: + # 配置结果集属性为空时 是否映射返回结果 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用 + mapper-locations: classpath:mapper/**/*.xml,classpath:com/casic/dao/mapper/**/*.xml +#mybatis: +# mapper-locations: classpath:mapper/*.xml +#mybatis-plus: +# sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector +casic: + device: + gas-dector: + type: 101 + minutes: 60 + enable-local: false + host: 127.0.0.1 + port: 11320 + url: http://127.0.0.1:1164/test + +# type 可燃气体的设备类型 +# minutes: 燃气外协设备上传数据的分钟数 \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..c0c7ac9 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + utf-8 + + + + + + + + + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + utf-8 + + + + + + + + ${LOG_PATH}/missiles_error.log + + + + + + ${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log + + + + 10MB + + + + + true + + + + ${FILE_LOG_PATTERN} + utf-8 + + + + + error + ACCEPT + DENY + + + + + + + + ${LOG_PATH}/missiles_total.log + + + + + + ${LOG_PATH}/total/log-total-%d{yyyy-MM-dd}.%i.log + + + + 10MB + + + + + true + + + + ${FILE_LOG_PATTERN} + utf-8 + + + + + + + + + + + \ No newline at end of file